我该怎么读缓冲读卡器?

时间:2010-03-23 13:15:30

标签: java bufferedreader readline ioexception

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

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的方法,我在Thread的run方法中使用了这段代码。当我尝试将throws Exception放在编译器抱怨的run之前:重写方法不会抛出异常。没有throws exception我还有另一个来自编译器的抱怨:未报告的异常。那么,我该怎么办?

9 个答案:

答案 0 :(得分:5)

当另一端的套接字关闭时,阅读器应返回一个空字符串。这是您正在寻找的条件。要处理异常,请将读取循环包装在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读取/写入套接字时很有帮助。

答案 1 :(得分:3)

关于您的第一个问题:

  

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

成功后,

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

您的第二个问题:

  

上面的代码取自抛出Exception的方法,我在Thread的run方法中使用了这段代码。当我在运行之前尝试放置抛出异常时,编译器会抱怨:重写方法不会抛出异常。没有抛出异常,我还有另一个来自编译器的抱怨:未报告的异常。那么,我该怎么办?

您应该将代码包装在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
}

答案 2 :(得分:1)

读者的readLine()将在读取内容时返回字符串值,在没有任何内容时返回空字符串,并在连接关闭时返回null。

我建议使用IO函数在try代码块周围包装try / catch并正确处理错误。

答案 3 :(得分:0)

input读者已连接到套接字,该套接字是一个监听器,即继续监听传入的消息。

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

答案 4 :(得分:0)

  

但我不明白它是如何运作的。 ....等待直到出现的东西   缓冲读者和什么时候   出现在那里它返回true

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

答案 5 :(得分:0)

到达“EOF(文件结束)”时返回

null。由于这是从网络套接字读取,因此在套接字断开连接时(由服务器或客户端)创建文件末尾,但在实际看到EOF之前,您可能会收到异常。

答案 6 :(得分:0)

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

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

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

答案 7 :(得分:0)

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

查看表达式的每个部分:

input.readLine()

返回一个String,如果已到达流的末尾将为null(或者在出错时抛出异常)。

inputLine = input.readLine()

将此String指定给inputLine

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

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

答案 8 :(得分:0)

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

至于readLine()的结果,当没有其他内容可供阅读时,它会返回null。在套接字的情况下,这是当另一边干净地关闭套接字时(任何突然终止或不清洁关闭通常会导致代码中的异常,因为操作系统将发送不同类型的套接字关闭通知)。

由于您在java.io.BufferedReader中包装套接字,我确实有一个警告。在任何类型的生产代码中使用它都应该非常小心。

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

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

如果在任何例外情况下您的设计是立即关闭阅读器和套接字,该方法将正常工作。

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