【问题标题】:BufferedReader not stating 'ready' when it shouldBufferedReader 没有在应该的时候声明“准备好”
【发布时间】:2011-06-13 04:50:32
【问题描述】:

我正在尝试通过 URL 上的 InputStreamReader 使用 BufferedReader 从 Web 文档中读取文本(到某些 Apache 服务器上的文件)。

String result = "";
URL url = new URL("http://someserver.domain/somefile");
BufferedReader in = null;
in = new BufferedReader(new InputStreamReader(url.openStream(), "iso-8859-1"));

result += in.readLine();

现在这工作得很好。但很明显,我希望读者不要只阅读一行,而是尽可能多地阅读文件中的内容。
查看 BufferedReader API,以下代码应该可以做到这一点:

while (in.ready()) {
    result += in.readLine();
}

即当有更多行时阅读所有行,当没有更多行时停止。然而,这段代码不起作用——读者只是从不报告ready() = true

我什至可以在读取一行之前打印 ready() 值(从文件中读取正确的字符串),但阅读器会报告“false”。

我做错了吗?为什么 BufferedReader 在实际有要读取的内容时返回“false”?

【问题讨论】:

  • 我不知道它是否重要,但 URL 实际上指向使用 HTTPS 的位置。但是,证书已正确安装在服务器和运行上述代码的机器上。 readLine() 也毫无问题地返回第一行。
  • 当有等待数据时它会准备好,但是直到你执行 read/readLine 才会有等待数据。即使有数据在等待,也可能不是完整的行,所以 readLine() 无论如何都会阻塞。
  • 很多很好的答案,谢谢每一个。可悲的是,我只能将一个标记为已接受的答案。 :)

标签: java url bufferedreader


【解决方案1】:

ready() != 有更多

ready() 并不表示还有更多数据要读取。它仅显示读取 是否会阻塞线程。在您读取所有数据之前,它很可能会返回 false。

如果没有更多数据,请检查readLine() 是否返回null

String line = in.readLine();
while(line != null){
   ...
   line = in.readLine();
}

【讨论】:

    【解决方案2】:

    另一种绕过in.ready() 的方法是:

    while ((nextLine = in.readLine()) != null) {
      result += nextLine;
    }
    

    您将继续阅读,直到完成。这样你就不用担心in.ready()的问题了。

    【讨论】:

    • 我认为你已经破坏了你的答案,因为它听起来像是一种解决方法。您展示的是从 BufferedReader 中读取的最常见习语,但更重要的是,它是正确的。像 OP 那样使用 ready() 方法是正确的。
    【解决方案3】:

    我认为编写此代码的标准方法是尝试读取该行并验证它是否在某个时间返回。像这样的:

    while ((String nextLine = in.readLine()) != null) {
        //System.out.println(nextLine);
        result += nextLine;
    }
    

    因此,您只需继续前进,直到从流中返回 null。有关更多信息,请参见此处:

    http://download.oracle.com/javase/1.5.0/docs/api/java/io/BufferedReader.html#readLine()

    【讨论】:

    • 对不起,我不应该说“标准”方式,而是我最常看到的方式。
    • 另外——在构造大字符串时不要忘记使用 StringBuffer(或者,StringBuilder 用于非同步操作):download.oracle.com/javase/1.5.0/docs/api/java/lang/…
    • 不,这很标准,尽管它不是有效的 Java(String 而不是 string,并且该声明需要在表达式之外)。我使用的成语是for (String l = null; (l = in.readLine()) != null; ) {
    • 啊,我的错。我猜想把我的 C# 和 Java 搞混了!很抱歉@Glenn Nelson。
    • 比方说,这是最令人困惑的写法。它来自 C 编译器很难优化任何东西的时候,所以你必须帮助他们使用赋值作为值和类似的有趣的东西。如果写得正确,它会导致字符串在太大的范围内可见。但是 - 它与 ready() 不起作用有什么关系???
    【解决方案4】:

    BufferedReader.ready() 方法的行为与指定的一样:

    Reader.ready() javadoc 表示以下内容:

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

    然后BufferedReader.ready() javadoc 说如下:

    判断此流是否已准备好被读取。如果缓冲区不为空,则缓冲的字符流已准备就绪,或者如果底层字符流已准备好

    如果将这两者放在一起,很明显BufferedReader.ready() 可以在字符可用的情况下返回false。简而言之,您不应该依赖 ready() 来测试逻辑文件结尾或流结尾。

    【讨论】:

      【解决方案5】:

      这是我们多年来一直使用的方法 - 不确定它是否是“标准”方法。我想听听 cmets 关于直接使用 URL.openURLStream() 的优缺点,以及这是否导致了 OP 的问题。此代码适用于 HTTP 和 HTTPS 连接。

       URL  getURL = new URL (servletURL.toString() + identifier+"?"+key+"="+value);      
       URLConnection uConn = getURL.openConnection();
      
       BufferedReader br = new BufferedReader (new
                                  InputStreamReader (uConn.getInputStream()));
       for (String s = br.readLine() ; s != null ; s = br.readLine()) {
            System.out.println ("[ServletOut] " + s);
            // do stuff with s
       }               
       br.close();
      

      【讨论】:

        【解决方案6】:

        基本上 BufferedReader.ready() 方法可用于检查底层流是否准备好向方法调用者提供数据......否则我们可以等待线程一段时间直到它准备好。

        但真正的问题是,当我们完全读取数据流后,它会抛出 false.. 所以我们不知道流是完全读取还是底层流忙....

        【讨论】:

        • 欢迎来到 StackOverflow。请务必查看如何使用Markdown 格式。这将使您的答案对其他人更有用。
        【解决方案7】:

        如果你想使用 in.ready(),以下对我很有效:

            for (int i = 0; i < 10; i++) {
                System.out.println("is InputStreamReader ready: " + in.ready());
                if (!in.ready()) {
                    Thread.sleep(1000);
                } else {
                    break;
                }
            }
        

        【讨论】:

        • 你能详细说说你的意图吗?
        猜你喜欢
        • 1970-01-01
        • 2014-09-19
        • 2015-10-13
        • 2019-08-04
        • 2013-10-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多