Reputation: 833
I've spent the last couple of hours searching the internet and my Java book for answers, but I've finally resorted to post a question on here. I'm trying to break out of a while loop once the user inputs 'DONE', but when I enter done it doesn't break out of the loop. How can I correct this problem.
Here is my code:
import java.io.*;
import java.util.Scanner;
public class Murray_A04Q2 {
public static void main(String[] args) throws IOException {
// Name of the file
String fileName = "userStrings.txt";
Scanner scan = new Scanner(System.in);
try {
// FileReader reading the text files in the default encoding.
FileWriter fileWriter = new FileWriter("userStrings.txt");
// Wrapping FileReader in BufferedReader.
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter outFile = new PrintWriter (bufferedWriter);
// InputStreamReader & BufferedReader for user input
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String input = "";
System.out.print("Enter something (DONE to quit): ");
input = scan.nextLine();
while (true) {
System.out.println("Enter something else or DONE to quit: ");
input = scan.nextLine();
input = br.readLine();
System.out.println(input);
if ((input = scan.nextLine()).equalsIgnoreCase("DONE")){
break;
}
}
bufferedWriter.write(input);
// Closing file
bufferedWriter.close();
}
catch (IOException ex){
System.out.println("Error writing to file " + "userStrings.txt" + "");
}
} // End of method header
} // End of class header
Thanks for your help in advance!
Upvotes: 0
Views: 234
Reputation: 729
The problem looks like it comes from reading from the same input stream from two readers at the same time (as well as having a rather excessive number of readLine() calls)
Here are where the errors APPEAR to be in your code:
import java.io.*;
import java.util.Scanner;
public class Murray_A04Q2 {
public static void main(String[] args) throws IOException {
String fileName = "userStrings.txt";
// Here you create a scanner using Standard Input as the input
// stream. (This is fine)
Scanner scan = new Scanner(System.in);
try {
// You say this is a FileREADER though it is clearly not...
// fix this comment!
// Either have remotely correct comments or just remove them.
FileWriter fileWriter = new FileWriter("userStrings.txt");
// Once again these are WRITERS not READERS.
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter outFile = new PrintWriter(bufferedWriter);
// Despite bad comments, the above code is NOT a problem.
// You just created a scanner, using it for input.
// Why make a second object to read from the SAME input stream?
// Not only does this cause confusion in how the stream is handled,
// but its useless code when you already have a Scanner.
// Remove these two objects and all references to them and
// replace them with the Scanner reference (or vice versa).
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
// Setting to emptyquotes is useless unless you are using the
// variable before its next write. Still, not the error.
String input = "";
System.out.print("Enter something (DONE to quit): ");
// Begin problems. You are reading in a line here,
// and once again, YOU ARE DOING >NOTHING< with it
// before the next write. In your print you say
// "DONE to quit" but you are NOT checking if
// input.equals("DONE")
input = scan.nextLine();
while (true) {
System.out.println("Enter something else or DONE to quit: ");
// Stream Read number 2, variable write number 3, still you
// have not READ from the input variable.
input = scan.nextLine();
// Stream Read number 3, variable write number 4, still you
// have not READ from the input variable.
// Also, despite you using a different reader, this is still
// accessing and pulling data out of the same input stream.
// Whatever the Scanner has pulled out is no longer in the
// input stream.
input = br.readLine();
// Finally you are reading the string in the variable
// 'input'. On the first iteration of the while loop you
// will have written to input 3 times already. You will
// only be printing the 3RD LINE of input from the user.
// Still however, you are not checking if
// input.equals("DONE") which is supposed to be the
// condition terminating your loop.
System.out.println(input);
// Stream read number 4, variable write number 5, FINALLY
// checking the user's input against the string "DONE" and
// terminating the loop. On the first iteration of the loop,
// this stream read will only see the 4TH line of input from
// the user.
if ((input = scan.nextLine()).equalsIgnoreCase("DONE")) {
break;
}
}
bufferedWriter.write(input);
// Closing file
bufferedWriter.close();
}
catch (IOException ex) {
System.out.println("Error writing to file " + "userStrings.txt"
+ "");
}
} // End of method header
} // End of class header
Given the following example user data:
DONE
Hello World!
Java is kool.
Time to squash bugs.
Done
dONe
lol nope
here is what your code is doing, line by line, from the first nextLine() call.
First read from stream (before loop, input = scan.nextLine();
)
What is happening: input = "DONE";
The first line, "DONE" is removed from the input stream and assigned to input
. input
's previous value, (empty string) is lost.
Second read from the stream (in loop, input = scan.nextLine();
)
What is happening: input = "Hello World!";
The second line, "Hello World!" is removed from the input stream and assigned to input
. input
's previous value, DONE
is lost.
Third read from the stream (in loop, input = br.readLine();
)
What is happening: input = "Java is kool.";
The third line, "Java is kool." is removed from the input stream and assigned to input
. input
's previous value, "Hello World!" is lost.
Output to Standard Output stream (in loop, System.out.println(input);
)
What is happening: System.out.println("Java is kool.");
The third line, "Java is kool." is printed to the standard output stream (System.out).
Fourth read from the stream (in loop, input = scan.nextLine();
)
What is happening: input = "Time to squash bugs.";
The fourth line, "Time to squash bugs." is removed from the input stream and assigned to input
. input
's previous value, "Java is kool" is lost.
equalsIgnoreCase(String) called on result of assignment (in loop, (input = scan.nextLine()).equalsIgnoreCase("DONE")
)
What is happening: "Time to squash bugs.".equalsIgnoreCase("DONE")
The fourth line of input, "Time to squash bugs." is tested to see if the strings are equal, ignoring all capitalization. They are not, so the if
block is skipped. There is no else
so code execution continues on after the if
block.
END OF LOOP. At this point nothing has forcefully terminated the loop so execution goes back to the loop's condition. The condition (true
) allows the loop to execute, so it starts at the top again.
Fifth read from stream (in loop, input = scan.nextLine();
)
What is happening: input = "Done";
The fifth line, "Done" is removed from the input stream and assigned to input
. input
's previous value, "Time to squash bugs." is lost.
Sixth read from the stream (in loop, input = br.readLine();
)
What is happening: input = "dONe";
The sixth line, "dONe" is removed from the input stream and assigned to input
. input
's previous value, "Done" is lost.
Output to Standard Output stream (in loop, System.out.println(input);
)
What is happening: System.out.println("dONe");
The sixth line, "dONe" is printed to the standard output stream (System.out).
Seventh read from the stream (in loop, input = scan.nextLine();
)
What is happening: input = "lol nope";
The seventh line, "lol nope" is removed from the input stream and assigned to input
. input
's previous value, "dONe" is lost.
equalsIgnoreCase(String) called on result of assignment (in loop, (input = scan.nextLine()).equalsIgnoreCase("DONE")
)
What is happening: "lol nope".equalsIgnoreCase("DONE")
The seventh line of input, "lol nope" is tested to see if the strings are equal, ignoring all capitalization. They are not, so the if
block is skipped. There is no else
so code execution continues on after the if
block.
END OF LOOP. At this point nothing has forcefully terminated the loop so execution goes back to the loop's condition. The condition (true) allows the loop to execute, so it starts at the top again.
In the example input there is no more input after "lol nope" so the next call to scan.nextLine()
blocks and the program freezes, unable to do anything until there is an input. With the way your code is currently set up, only every third line after (and including) the fourth line of user input will be read in and checked for equality against "DONE".
DONE
Hello World!
Java is kool.
Time to squash bugs.
Done
dONe
lol nope
First fix: get rid of variables isr
and br
altogether and just use scan
(or vice versa, get rid of scan
and use isr
and br
). Since they are pulling data from the same input stream they are doing the same job in almost the same way creating unnecessary and confusing code.
Second fix: if you are not doing anything with the input variable between calls to readLine() or nextLine() and you are not using the calls to eliminate trash input data, GET RID OF THEM. You call readLine() or nextLine() once and store it to input
and the value stays until the next assignment to input
.
IF you are in fact using multiple calls to readLine() or nextLine() to retrieve user data, but that data MIGHT include "DONE" then you will need to replace the calls to readLine() or nextLine() with your if block, since it reads the input and immediately checks to see if it equals "DONE".
Some possible fixes to your code, depending on what your needs are (I'm assuming you trimmed code you didn't think was relevant or that simply hasn't been added yet.)
import java.io.*;
import java.util.Scanner;
public class Murray_A04Q2 {
public static void main(String[] args) throws IOException {
String fileName = "userStrings.txt";
Scanner scan = new Scanner(System.in);
try {
FileWriter fileWriter = new FileWriter("userStrings.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter outFile = new PrintWriter(bufferedWriter);
String input;
System.out.print("Enter something (DONE to quit): ");
if (!(input = scan.nextLine()).equalsIgnoreCase("DONE")) { // Added "!" (not)
// Some one time use code goes here.
System.out.println("Enter something else or DONE to quit: ");
while (true) {
if ((input = scan.nextLine()).equalsIgnoreCase("DONE")) {
break;
}
// Some code goes here
if ((input = scan.nextLine()).equalsIgnoreCase("DONE")) {
break;
}
// Some DIFFERENT code goes here.
System.out.println(input);
if ((input = scan.nextLine()).equalsIgnoreCase("DONE")) {
break;
}
// Some code that didn't belong above can go here.
}
}
bufferedWriter.write(input);
bufferedWriter.close();
}
catch (IOException ex) {
System.out.println("Error writing to file " + "userStrings.txt"
+ "");
}
}
}
Also:
import java.io.*;
import java.util.Scanner;
public class Murray_A04Q2 {
public static void main(String[] args) throws IOException {
String fileName = "userStrings.txt";
Scanner scan = new Scanner(System.in);
try {
FileWriter fileWriter = new FileWriter("userStrings.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter outFile = new PrintWriter(bufferedWriter);
String input;
System.out.print("Enter something (DONE to quit): ");
if (!(input = scan.nextLine()).equalsIgnoreCase("DONE")) { // Added "!" (not)
// Some one time use code goes here.
System.out.println("Enter something else or DONE to quit: ");
while ((input = scan.nextLine()).equalsIgnoreCase("DONE")) {
System.out.println(input);
// Some code can go here.
}
}
bufferedWriter.write(input);
bufferedWriter.close();
}
catch (IOException ex) {
System.out.println("Error writing to file " + "userStrings.txt"
+ "");
}
}
}
OR if you want all your code to run inside the loop:
import java.io.*;
import java.util.Scanner;
public class Murray_A04Q2 {
public static void main(String[] args) throws IOException {
String fileName = "userStrings.txt";
Scanner scan = new Scanner(System.in);
try {
FileWriter fileWriter = new FileWriter("userStrings.txt");
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
PrintWriter outFile = new PrintWriter(bufferedWriter);
String input;
System.out.print("Enter something (DONE to quit): ");
while ((input = scan.nextLine()).equalsIgnoreCase("DONE")) {
System.out.println(input);
// Some code can go here.
System.out.println("Enter something else or DONE to quit: ");
}
bufferedWriter.write(input);
bufferedWriter.close();
}
catch (IOException ex) {
System.out.println("Error writing to file " + "userStrings.txt"
+ "");
}
}
}
Upvotes: 1
Reputation: 94
I suggest you first try with this reduced version of your implementation and after that, try adding all that you need with your file.
import java.util.Scanner;
public class Murray_A04Q2 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String input = "";
System.out.print("Enter something (DONE to quit): ");
input = scan.nextLine();
System.out.println(input);
while (!input.equalsIgnoreCase("DONE")) {
System.out.println("Enter something else or DONE to quit: ");
input = scan.nextLine();
System.out.println(input);
}
scan.close();
System.out.println("DONE!!");
}
}
Upvotes: 0
Reputation: 77226
You're wrapping a scanner around your reader and then trying to read from both of them simultaneously, which is making them fight over the available input. Eliminate the reads directly from the reader.
Upvotes: 0