0

I've been searching the web and I can't seem to find a working solution. I have a file containing theses lines:

Room 1
Coffee
Iron
Microwave
Room_end
Room 2
Coffee
Iron 
Room_end

I want to print all Strings between Room 1 and Room_end. I want my code to start when it find Room 1, print line after Room 1 and stop when it get to the first Room_end it find.

private static String LoadRoom(String fileName) {
        List<String> result = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
            result = reader.lines()
                    .dropWhile(line -> !line.equals("Room 1"))
                    .skip(1)
                    .takeWhile(line -> !line.equals("Room_end"))
                    .collect(Collectors.toList());
        } catch (IOException ie) {
            System.out.println("Unable to create " + fileName + ": " + ie.getMessage());
            ie.printStackTrace();
        }
        for (int i = 0; i < result.size(); i++) {
            System.out.println(result.get(i).getname());//error on getname because it cant work with Strings
        }
    }



    class Model {

        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

I am able to get a method to print all Strings of the file but not specific range of Strings. I also tried to work with Stream. My code feel quite messy, but I've been working on it for a while an it seems it only get messier.

2
  • type String has no method getname (nor getName) Commented Sep 9, 2022 at 4:14
  • You code won't compile. It's not returning a string. If the method is supposed to return a string, then there's no reason for it to print the string. Either it return the string, or print the string but with void return type. I think using stream is an overkill for this. Why not just use a scanner to read line by line? Commented Sep 9, 2022 at 6:33

4 Answers 4

1

I think there is a problem if you want to use lambda expression here:

lambda expressions are functional programming, and functional programming requires immutability, that means there should not be state related issue, you can call the function and give it same parameters and the result always will be the same, but in your case, there should be a state indicating whether you should print the line or not.

can you try this solution? I write it in python, but mainly it is just about a variable should_print that located outside of the scope

should_print = False
result = reader.lines()
for line in result:
    if line == "Room end":
        break
    if should_print:
        print(line)
    if line == "Room 1":
        should_print = True

keep a boolean value outside of the iteration, and check/update the value in each iteration

Sign up to request clarification or add additional context in comments.

3 Comments

Your solution will print "Room 1" which is not what he want. You should make the last if to elif.
thanks, that is my mistake, I changed it, I want to point out that PO should not implement this problem with stream/lambda expression, and I did not pay enough attention to the code
Thank you, i got lost into my coding. I will get back to the basic like you highlighted.
1
public static Map<String, List<String>> getRooms(String path) throws IOException {
    Map<String, List<String>> result = new HashMap<>();
    try (Scanner sc = new Scanner(new File(path))) {
        sc.useDelimiter("(?=Room \\d+)|Room_end");
        while (sc.hasNext()) {
            Scanner lines = new Scanner(sc.next());
            String room = lines.nextLine().trim();
            List<String> roomFeatures = new ArrayList<>();
            while (lines.hasNextLine()) {
                roomFeatures.add(lines.nextLine());
            }
            if (room.length() > 0) {
                result.put(room, roomFeatures);
            }
        }
    }
    return result;
}

is one way of doing it for your 'rooms file' though it should really be made more OO by making a Room bean to hold the data. Output with your file: {Room 2=[Coffee, Iron ], Room 1=[Coffee, Iron, Microwave]}

2 Comments

A minor addition, since Java 11 we have String.stip() and it's flavors as a replacement to trim().
@AlexanderIvanchenko Interesting. That's the first time I've come across that. The difference is subtle but I'm having a hard time thinking of when that might be useful ;)
0

Switched my code and used this:

    private static String loadRoom(String fileName) {
        BufferedReader reader = null;
        StringBuilder stringBuilder = new StringBuilder();

        try {
            reader = new BufferedReader(new FileReader(fileName));
            String line = null; //we start with empty info
            String ls = System.getProperty("line.separator"); //make a new line
            while ((line = reader.readLine()) != null) { //consider if the line is empty or not
                if (line.equals("Room 1")) { //condition start on the first line being "Room 1"
                    line = reader.readLine(); // read the next line, "Room 1" not added to stringBuilder
                    while (!line.equals("Room_end")) {    //check if line String is "Room_end"
                        stringBuilder.append(line);//add line to stringBuilder
                        stringBuilder.append(ls);//Change Line in stringBuilder
                        line = reader.readLine();// read next line
                    }
                }
                
            }
        stringBuilder.deleteCharAt(stringBuilder.length() - 1);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null)
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }

        return stringBuilder.toString();
    }

3 Comments

Fixed it. stringBuilder.deleteCharAt(stringBuilder.length() - 1); wasn't at the right place.
Just a small thing, you can break out all loop after reach “Room end “, now it seems like it will read the whole file/to the end after finding Room end
Yes thank you, file I was testing with had only 2 rooms in it. While i plan to go around 180 to 370 rooms. Break will be useful thx again!
0

Here's a solution that uses a scanner and a flag. You may choose to break the loop when it reads "Room_end"

import java.util.Scanner;
import java.io.*;
public class Main{
   private static String loadRoom(String fileName) throws IOException { 
        Scanner s = new Scanner(new File(fileName));
        StringBuilder sb = new StringBuilder();
        boolean print = false;
        while(s.hasNextLine()){
           String line = s.nextLine();
           if      (line.equals("Room 1"))   print = true;
           else if (line.equals("Room_end")) print = false;
           else if (print) sb.append(line).append("\n");
        }
        return sb.toString();
   }
    public static void main(String[] args)  {
       try {
          String content = loadRoom("content.txt");
          System.out.println(content);
       }catch(IOException e){
          System.out.println(e.getMessage());
       }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.