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

cha*_*nce 11 java file-io

我有这样的代码来使用BufferedReader以下方法读取文本文件:

BufferedReader reader=null;
    try {
        reader = new BufferedReader(new FileReader("file1.txt"));

        while (reader.ready()) {
            final String line = reader.readLine();
            System.out.println("<"+line+">");
        } catch (..)
    {
        ...
    }
Run Code Online (Sandbox Code Playgroud)

它工作正常但Findbugs报告警告:

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

当我换FileReaderStringReader,即

BufferedReader reader=null;
    try {
        reader = new BufferedReader(new StringReader("ABCD"));

        while (reader.ready()) {
            final String line = reader.readLine();
            System.out.println("<"+line+">");
        } catch (..)
    {
        ...
    }
Run Code Online (Sandbox Code Playgroud)

readLine方法返回null,而ready方法总是返回true-这确实是一个无限循环.

这似乎即使返回readLine也可能返回.但是为什么不同的行为会有所不同?nullreadytrueReader

更新:

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

输入什么时候会阻塞?如何使用该ready方法(或为什么不使用它)?为什么那些2 Readers(FileReaderStringReader)在ready方法方面表现不同?

Par*_*rag 15

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

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

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


Pet*_*rey 12

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

String line;
while ((line = reader.readLine()) != null)
    System.out.println("<"+line+">");
Run Code Online (Sandbox Code Playgroud)

  • 代码永远挂在该reader.readline()行上.有什么建议? (3认同)

And*_*yle 6

以下是Javadocs所说的内容:

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

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

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

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

  • 不幸的是,对于readLine(),ready()只保证一个字符可用,即read()不会阻塞.如果有数据但不是完整的行,readLine()将阻塞. (6认同)