简体   繁体   中英

Having trouble reading files in java

I have some trouble reading file in Java.

What a file looks like:

Answer 1:
1. This is an apple
2. Something
Answer 2:
1. This is a cool website 
2. I love banana
3. This is a table
4. Programming is fun
Answer 3. 
1. Hello World
.... 

What I want to do is separate them into two items: One is the Answer number; The other one is list of answers.

So assuming I have a object class called Answer: String of answer number List of answers.

This is what I have done so far to debug my code before I put it into object class. But I'm not able to get the correct result

public void reader(String file) throws FileNotFoundException, IOException {
    FileReader fR = new FileReader(file);
    BufferedReader bR = new BufferedReader(fR);
    String line = null;

    int count = 0 ;
    String blockNum = "";
    String printState = "" ;
    while ((line = bR.readLine()) != null) {
        if(line.contains("Answer")){
            //System.out.println("Contain Answer statement: " + line);
            count++;
            blockNum = line; 
            printState = "";
        }
        else{
            //System.out.println("No Answer Statement: " + line);
            printState += line + " / " ;
        }

        System.out.println( count + " " + blockNum + "   " + printState );
    }

    // Close the input stream
    bR.close();
    fR.close();
}

I'm pretty sure I did something stupid while I'm coding. I'm not too sure how to read it so that it will have separate it.

Right now the output looks like this:

1 Answer 1:   
1 Answer 1:   1. This is an apple / 
1 Answer 1:   1. This is an apple / 2. Something / 
2 Answer 2:   
2 Answer 2:   1. This is a cool website  / 
2 Answer 2:   1. This is a cool website  / 2. I love banana / 
2 Answer 2:   1. This is a cool website  / 2. I love banana / 3. This is a table / 
2 Answer 2:   1. This is a cool website  / 2. I love banana / 3. This is a table / 4. Programming is fun / 
3 Answer 3.    
3 Answer 3.    1. Hello World / 

But I want the output to be something like this:

1 Answer 1:   1. This is an apple / 2. Something / 
2 Answer 2:   1. This is a cool website  / 2. I love banana / 3. This is a table / 4. Programming is fun /    
3 Answer 3.    1. Hello World / 

You are printing a line of output for each line of input you read. Try moving the println inside the part of the loop that checks for answer to make sure you print each answer/answer value set only once. Eg:

if(line.contains("Answer")) {
    if (printState != "") {
        System.out.println(count + " " + blockNum + "   " + printState);
    }
    ...
}

EDIT: You will also need to print when you exit the while loop to make sure you print the last answer/answer value set.

One solution use a flag for printTime as a boolean.

boolean printTime = false;

...
   if(line.contains("Answer")) {

       if (printTime!= false) {
          System.out.println( count + " " + blockNum + "   " + printState );
          printTime=false;
       }
        ...
  }else{
        //System.out.println("No Answer Statement: " + line);
        printState += line + " / " ;
        printTime=true; // you have one answer 
  }
  ...    

add a little extra print at the end of the while for last answer

that way you can have several printState for one answer in one line.

But correct "java" way of handle this is to create your objects:

List<Answer> listOfAnswer = new LinkedList<Answer>();
Answer answer;
...
if(line.contains("Answer")){
            //System.out.println("Contain Answer statement: " + line);
            count++;

            answer = new Answer(line);
            listOfAnswer.add(answer)
        }
        else{
            answer.add(new Answer(line));
        }
}
...

and only after print them out :)

System.out.println(listOfAnswer.toString());

Simpler solution is to use a

Map<Integer, LinkedList<String>> answers = new LinkedHashMap<Integer, LinkedList<String>();

See working example:

public void reader(String file) throws FileNotFoundException,
        IOException {
    BufferedReader reader = new BufferedReader(new FileReader(file));
    String line = "";
    while (reader.ready()) {
        line = reader.readLine();
        if (!line.contains("Answer")) {
            System.out.print(line + " / ");
        } else {
            System.out.println();
            System.out.print(line + " ");
        }
    }
}

The main output issue is that you are printing inside the line-iterating loop (while).

To solve it, you can follow what @Albion answered and change where the print is done inside the while , but as the EDIT on his answer states, there is a flaw and you will have to print an extra time after the loop, in order to get the correct result.

There is an alternative tough, that is to not print it inside the loop at all, which i consider to be the correct approach in your case. To do it, you need little more than using StringBuilder instead of String!


I have also spotted some needless variables, and there is also a flaw in using the if(line.contains("Answer")) method, that is that if "Answer" string appears inside one of the options texts, it will get a true and mess your results, for example:

Answer 1:
1. This is an apple
2. Capitalizing Is The Answer!
3. Something

Will output:

1 Answer 1:  1. This is an apple / 
2 2. Capitalizing Is The Answer!  3. Something

In most cases, the best approach to finding a dynamic pattern (as yours is, for it changes the number and, in the last Answer, the ' : ' with a ' . ' too) is to use a (pattern) Matcher! I used this: if(line.matches("Answer \\\\d[\\\\:\\\\.]")) , and if you are not yet used to it, see the Pattern Docs , as String.matches() is something you will probably use a lot when processing text.


Explaining every single change is a little troublesome, and the code is simple enough for you master after you analyse it, so i'll simply post what my approach would be:

public static void StackAnswer(String file) throws FileNotFoundException, IOException{
    BufferedReader br = new BufferedReader(new FileReader(file));
    StringBuilder output = new StringBuilder();
    int count = 0;
    while(br.ready()){
        String line = br.readLine().trim();
        if(line.matches("Answer \\d[\\:\\.]")){
            count++;
            output.append(System.lineSeparator()).append(count).append(' ').append(line);
        } else {
            output.append(" / ").append(line);
        }
    }
    System.out.println(output.toString().trim());
    br.close();
}

Good luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM