我正在尝试在我的Java程序中读取stdin。我期待一系列数字后跟新行,例如:
6
9
1
通过eclipse内置控制台提供输入时,一切顺利。但是当使用Windows命令行时,程序会打印:
Received '6'.
Received 'null'.
Invalid input. Terminating. (This line is written by another function that does an Integer.parseint()).
我的代码是:
static String readLineFromStdIn(){
try{
java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
String input = new String();
input = stdin.readLine();
System.out.println("Received '" + input + "'");
return(input);
}catch (java.io.IOException e) {
System.out.println(e);
}
return "This should not have happened";
}
任何线索?
答案 0 :(得分:8)
您得到null
表示相关的Reader
个对象已达到EOF(文件末尾),换句话说,他们无法获得更多标准输入。现在,代码的明显问题是:
readLineFromStdIn()
的方法都会创建一个 new BufferedReader
。 BufferedReader
将相互“竞争”来自System.in
BufferedReader
个对象都没有被正确关闭,因此每次调用readLineFromStdIn()
时,您的程序都会泄漏I / O资源。解决方案是在BufferedReader
的每次调用中使用单个共享readLineFromStdIn()
对象。
答案 1 :(得分:2)
这个问题并不是一个新的答案,但我想在评论中澄清原始代码为何如此表现的混淆(我不能发表评论,因为我是ST的新手,并没有获得声誉点)。
null结果与垃圾收集无关。即使两个读者仍然活着,可访问的对象,下面的程序也会遭遇完全相同的命运:
BufferedReader r1 = new BufferedReader(new InputStreamReader(System.in));
System.out.println(r1.readLine());
BufferedReader r2 = new BufferedReader(new InputStreamReader(System.in));
System.out.println(r2.readLine());
这一切都归结为BufferedReader
中“缓冲”的含义。它是Reader
,包括内部缓冲。内部缓冲通常显着提高对底层流的操作效率,例如,通过尝试每次读取一个完整的缓冲区的价值,而不是在这里获取几个字节并在那里获取一些字节的流量和流量。
那么当您在stdin上创建第一个BufferedReader
并从中读取一行时会发生什么? BufferedReader
从流中读取缓冲区已满,检测到行尾,返回第一行,并挂起到缓冲区的其余部分以填充其下一个请求。这使得底层流位于第一行的末尾之外。如果您的输入很小,可以轻松定位到EOF。
所以现在你来到同一个流的顶部创建第二个BufferedReader - 它在EOF上 - 并试图获得一条线。第二个BufferedReader尝试从底层流中读取并检测EOF,因此readLine
返回null
。