readline()在Java中返回null

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()). 我的

我正在尝试读取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";  
}  

有什么线索吗?

如果您得到一个
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
    调用之前关闭(因此为空,试图从关闭的
    系统中读取)。