【问题标题】:How should I read from a buffered reader?我应该如何从缓冲阅读器中阅读?
【发布时间】:2010-03-23 13:15:29
【问题描述】:

我有以下从缓冲阅读器读取的示例:

while ((inputLine = input.readLine()) != null) {
   System.out.println("I got a message from a client: " + inputLine);
}

循环中的代码println 将在缓冲阅读器中出现任何内容时执行(在本例中为input)。在我的例子中,如果客户端应用程序向套接字写入内容,循环中的代码(在服务器应用程序中)将被执行。

但我不明白它是如何工作的。 inputLine = input.readLine() 等到缓冲阅读器中出现某些内容,当那里出现某些内容时,它返回 true 并执行循环中的代码。但是当null可以返回。

还有一个问题。上面的代码取自 throws Exception 的方法,我在线程的 run 方法中使用了这段代码。当我尝试将throws Exception 放在run 之前时,编译器会抱怨:被覆盖的方法不会引发异常。没有throws exception,编译器还有另一个抱怨:​​未报告的异常。那么,我该怎么办?

【问题讨论】:

  • @Roman - 你知道这笔交易。将不同的问题放在不同的 SO Questions 中!!
  • Stephen C,我认为添加的部分也是“我应该如何从缓冲阅读器中读取?”的一部分。但我明白你的意思。我删除了添加的部分。

标签: java bufferedreader readline ioexception


【解决方案1】:

当另一端的套接字关闭时,阅读器应该返回一个空字符串。这是您正在寻找的条件。要处理异常,请将读取循环包装在 try/catch 块中。

 try {
   while ((inputLine = input.readLine()) != null) {
     System.out.println("I got a message from a client: " + inputLine);
   }
 }
 catch (IOException e) {
   System.err.println("Error: " + e);
 }

你可能会发现这个tutorial 对 Java 中的套接字进行读/写很有帮助。

【讨论】:

    【解决方案2】:

    第一个问题:

    但我不明白它是如何工作的。 inputLine = input.readLine() 一直等到缓冲阅读器中出现某些内容,当那里出现某些内容时,它返回 true 并执行循环中的代码。但是什么时候可以返回null。

    BufferedReader.readLine() 成功后不会返回true。它返回一个包含已读取行的字符串。如果到达流的末尾,则返回null

    您的第二个问题:

    上面的代码取自一个抛出异常的方法,我在线程的运行方法中使用了这个代码。当我尝试在运行之前抛出异常时,编译器会抱怨:被覆盖的方法不会抛出异常。如果没有 throws 异常,我还有编译器的另一个抱怨:​​未报告的异常。那么,我该怎么办?

    您应该将代码包装在try/catch block 中。如果您不想处理捕获的异常,只需将该部分留空(不推荐)

    try {
        while ((inputLine = input.readLine()) != null) {
            System.out.println("I got a message from a client: " + inputLine);
        }
    } catch (Exception e) {
        //handle exception
    }
    

    【讨论】:

      【解决方案3】:

      阅读器的 readLine() 将在读取到内容时返回一个字符串值,在还没有任何内容时返回一个空字符串,在连接关闭时返回 null。

      我建议使用 IO 函数将 try/catch 包裹在您的代码块周围,并适当地处理错误。

      【讨论】:

        【解决方案4】:

        input reader 连接到socket,它是一个监听器,即不断监听传入的消息。

        关于你的第二个问题,你应该在方法中放置一个 try/catch 块,捕获异常并处理它。不要再扔了。

        【讨论】:

          【解决方案5】:

          但我不明白它是如何工作的。 .... 等到某些东西出现在 缓冲阅读器和什么时候 出现在那里它返回true

          不,它返回表达式 (inputLine = input.readLine()) 的值,即 inputLine 本身。 inputLine 与 null 进行比较。

          【讨论】:

            【解决方案6】:

            当到达“EOF(文件结尾)”时返回null。由于这是从网络套接字读取的,因此当套接字断开连接(由服务器或客户端)时会创建文件结尾,但您可能会在实际看到 EOF 之前得到一个异常。

            【讨论】:

              【解决方案7】:

              如果这不是家庭作业,您可能需要查看 Apache Commons IOUtils

              假设您没有创建 BufferedReader,而只是停在 InputStream:

              String results = IOUtils.toString(inputStream);
              System.out.println(results);
              

              【讨论】:

                【解决方案8】:
                while ((inputLine = input.readLine()) != null) {
                

                查看表达式的每个部分:

                input.readLine()
                

                如果已到达流的末尾,则返回一个为空的字符串(或在错误时引发异常)。

                inputLine = input.readLine()
                

                将此字符串分配给 inputLine

                ((inputLine = input.readLine()) != null)
                

                检查分配的字符串不为空(流结束)。

                【讨论】:

                  【解决方案9】:

                  您收到了一些很好的答案。只需捕获异常并在本地处理即可。如果您需要将此传递给其他代码,但由于 run() 方法不允许任何检查异常而不能,您可以将异常包装在某种 RuntimeException 中。如果 run 方法直接在 Thread 上执行(因为它可能是 Runnable),那么您应该注意重新抛出包装的异常。

                  对于readLine() 的结果,当没有更多内容可读取时,它将返回null。在套接字的情况下,这是当另一端干净地关闭套接字时(任何突然终止或不干净的关闭通常会导致您的代码出现异常,因为操作系统将发送不同类型的套接字关闭通知)。

                  我确实有一点要注意,因为您将套接字包装在 java.io.BufferedReader 中。在任何类型的生产代码中使用它时都应该非常小心。

                  危险在于 BufferedReader 不能很好地处理读取过程中的异常。如果您在套接字上启用了超时,这尤其是一个问题,因此代码将自动从操作系统接收定期异常。读取器内的缓冲区正在填充时,超时(或其他异常)可能会出现。如果您尝试在异常发生后重用该对象,它将忽略缓冲区中任何先前的内容。之前收到的数据包会自动丢失,并且无法检索这些字节。

                  请注意,还有其他类型的套接字异常并不意味着套接字已丢失。例如,查看java.io.InterruptedIOException 的定义。这有一个公共变量报告在最近的 I/O(读或写)请求中成功传输的字节数。这意味着可以再次执行 IO 操作以检索或发送数据包的剩余字节。

                  如果出现任何异常,您的设计是立即关闭阅读器和套接字,该方法将正常工作。

                  从套接字读取的正确方法是直接使用套接字流,使用 NIO(ByteBuffers 等),或者使用编写良好的网络库,对这些较低级别的类进行良好的抽象(有几个开源类可用) .

                  【讨论】:

                    猜你喜欢
                    • 2023-03-28
                    • 2018-06-14
                    • 2017-09-23
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-07-08
                    • 1970-01-01
                    • 2011-10-23
                    相关资源
                    最近更新 更多