BufferedReader.ready()方法是否确保readLine()方法不返回NULL?

我有这样的代码使用BufferedReader读取文本文件:

 BufferedReader reader=null; try { reader = new BufferedReader(new FileReader("file1.txt")); while (reader.ready()) { final String line = reader.readLine(); System.out.println(""); } catch (..) { ... } 

它工作正常,但Findbugs报告一个警告:

NP_DEREFERENCE_OF_READLINE_VALUE:取消引用调用readLine()的结果,而不检查结果是否为null。 如果没有更多的文本行要读取,readLine()将返回null并解除引用将生成空指针exception。

当我将FileReader更改为StringReader ,即

 BufferedReader reader=null; try { reader = new BufferedReader(new StringReader("ABCD")); while (reader.ready()) { final String line = reader.readLine(); System.out.println(""); } catch (..) { ... } 

readLine方法返回nullready方法总是返回true – 实际上这是一个无限循环。

这似乎即使ready返回truereadLine也可能返回null 。 但是为什么不同Reader的行为会有所不同?

更新:

我知道读取文本文件的正常方法(就像Peter和Ali所说的那样)。 但我从同事那里读到了那段代码,并意识到我不知道ready方法。 然后我读了JavaDoc,但是不懂block 。 然后我做了一个测试并发布了这个问题。 所以,提出这个问题的更好方法可能是:

输入什么时候会阻塞? 如何使用ready方法(或者为什么不使用它)? 为什么这两个ReaderFileReaderStringReader )在ready方法方面表现不同?

ready方法告诉我们Stream是否准备好被读取。

想象一下,您的流正在从网络套接字读取数据。 在这种情况下,流可能没有结束,因为套接字尚未关闭,但它可能还没有为下一个数据块做好准备,因为套接字的另一端没有再推送任何数据。

在上面的场景中,我们无法再读取任何数据,直到远程端推送它,因此我们必须等待数据可用,或者关闭套接字。 ready()方法告诉我们数据何时可用。

Reader.ready()和InputStream.available()很少像你想的那样工作,我不建议你使用它们。 要阅读您应该使用的文件

 String line; while ((line = reader.readLine()) != null) System.out.println("<"+line+">"); 

这是Javadocs所说的:

判断此流是否可以读取。 如果缓冲区不为空,或者基础字符流已准备就绪,则缓冲字符流就绪。

因此,如果底层流也准备就绪,则认为BufferedReader已准备就绪。 由于BufferedReader是一个包装器,因此这个底层流可以是任何Reader实现; 因此ready()的语义是在接口上声明的语义:

如果保证下一个read()不阻止输入,则返回true,否则返回false。 请注意,返回false并不能保证下一次读取将被阻止。

因此,您只能获得时序保证,即read()不会阻塞。 调用ready()的结果绝对不会告诉您从read()调用中获取的内容 ,因此不能用于忽略空检查。

看看API准备好了 。

你做的是错的。 ready()仅告诉您流是否可读且有效。 阅读该链接上的返回评论。

你想要做的是:

 String thisLine; //Loop across the arguments for (int i=0; i < args.length; i++) { //Open the file for reading try { BufferedReader br = new BufferedReader(new FileReader(args[i])); while ((thisLine = br.readLine()) != null) { // while loop begins here System.out.println(thisLine); } // end while } // end try catch (IOException e) { System.err.println("Error: " + e); } } // end for