readline()在Java中返回null
我正在尝试读取Java程序中的stdin。我期待着一系列的数字,然后是换行符,比如:readline()在Java中返回null,java,stdin,readline,Java,Stdin,Readline,我正在尝试读取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()). 我的
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";
}
有什么线索吗?如果您得到一个
null
,则表明相关的读取器
对象达到了EOF(文件结束),或者换句话说,它们无法获得更多的标准输入。现在,代码的明显问题是:
readLineFromStdIn()
的每个方法调用都将创建一个新的BufferedReader
李>
BufferedReader
将相互“竞争”来自系统的相同共享输入
BufferedReader
对象都没有正确关闭,因此程序每次调用readLineFromStdIn()
都会泄漏I/O资源解决方案是在每次调用
readLineFromStdIn()
时使用一个共享BufferedReader
对象,这并不是对这个问题的新答案,但我想澄清注释中关于原始代码为何如此行为的混淆(我不能发表评论,因为我是ST的新手,还没有获得声誉积分)
空结果与垃圾收集无关。即使两个读卡器仍然存在可访问的对象,以下程序也会遭受完全相同的命运:
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
中表示。它是一个包含内部缓冲的读取器
。内部缓冲通常会显著提高底层流上操作的效率,例如,每次都尝试读取一个完整缓冲区的值,而不是在此处获得几个字节,然后将流缩小到死亡状态那里几乎没有
那么,当您在stdin上创建第一个BufferedReader
并从中读取一行时会发生什么呢?BufferedReader
从流中读取一个已满的缓冲区,检测到行尾,返回第一行,并挂起缓冲区的其余部分以填充其下一个请求。这使得底层流位于en之外如果你的输入很小,它可以很容易地定位在EOF
现在,您开始在同一个流上创建第二个BufferedReader,它位于EOF,并尝试获取一行。第二个BufferedReader尝试从底层流读取数据并检测EOF,因此
readLine
返回null
我在Eclipse控制台中输入,所有数字后跟enter.in win我做的是“java-jarprogram.jarstdin
,从技术上讲,这意味着您正在打开一个文件流,并且永远不会关闭它,这超出了Java可以保持的打开文件连接数。@user268396请注意,如果此BufferedReader
如果关闭,它也会关闭System.in,这可能不太理想。这可能是一种罕见的情况,您只希望装饰程序流被GC'd而不被关闭。同意您不希望导致System.in被显式关闭。但是,当BufferedReader被GC'd时,它无论如何都会被关闭。在这种情况下,有终结器,IIRC。我猜在修复之前发生的是,在Windows VM上,临时的BufferedReader
对象被非常猛烈地GC'ed,因此导致STDIN在第二次readLineFromStdIn
调用之前关闭(因此为空,试图从关闭的系统中读取)。