readline()在Java中返回null

时间:2012-03-09 13:44:57

标签: 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()).  

我的代码是:

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";  
}  

任何线索?

2 个答案:

答案 0 :(得分:8)

您得到null表示相关的Reader个对象已达到EOF(文件末尾),换句话说,他们无法获得更多标准输入。现在,代码的明显问题是:

  1. 每次调用readLineFromStdIn()的方法都会创建一个 new BufferedReader
  2. 每个此类BufferedReader将相互“竞争”来自System.in
  3. 的相同共享输入
  4. 这些BufferedReader个对象都没有被正确关闭,因此每次调用readLineFromStdIn()时,您的程序都会泄漏I / O资源。
  5. 解决方案是在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