Returning Strings from a file between 2 specified strings in java

Viewed 69

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.

4 Answers

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

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]}

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();
    }

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());
       }
    }
}
Related