Suppose I have the following (silly) java program which cycles back and forth between main
and aux
, whenever a y
is typed:
import java.util.Scanner;
public class Minimal {
public static void main(String[] args) {
System.out.println("in main...");
Scanner scanner = new Scanner(System.in);
String s;
while(scanner.hasNextLine()) {
s = scanner.nextLine();
System.out.println(s);
if(s.equals("y")) {
aux();
System.out.println("in main...");
}
}
}
public static void aux() {
System.out.println("in aux...");
Scanner scanner = new Scanner(System.in);
String s;
while(scanner.hasNextLine()) {
s = scanner.nextLine();
System.out.println(s);
if(s.equals("y")) {
return;
}
}
}
}
But then, when I run
$ javac Minimal.java
$ printf "y\ny\ny\ny\ny\ny\ny\n" | java Minimal
in bash, I get a different answer than when running
$ java Minimal
and typing (interactively) y
followed by <ENTER>
--- seemingly equivalent to what was fed in automatically above with printf
. Any ideas?
The difference is because of buffering. Scanner
buffers its input, so it may consume more than one line at a time from System.in
. When you use printf
, the data is available immediately so it is all consumed by the Scanner
instance in main()
. As a result, there is no more data available for the Scanner
created in each call to aux()
to read.
When you run the program interactively, the terminal sends the data line by line as you enter it, so there isn't any extra data available to get buffered at each read.
To avoid this problem, don't create more than one instance of Scanner
for the same InputStream
.