2010-03-23 92 views
2

我有从缓冲读者阅读以下示例:我应该如何从缓冲读取器读取数据?

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

每当东西在缓冲读取器出现(input在这种情况下)在循环println的代码将被执行。就我而言,如果客户端应用程序向套接字写入某些内容,则会执行循环中的代码(在服务器应用程序中)。

但我不明白它是如何工作的。 inputLine = input.readLine()等待,直到出现在缓冲读取器中的东西出现,然后当它出现时返回true,并且循环中的代码被执行。但是,当null可以返回。

还有一个问题。上面的代码是从throws Exception和我在Thread的run方法中使用此代码的方法中获得的。当我试图在run之前放throws Exception时,编译器会抱怨:重写的方法不会抛出异常。没有throws exception我有另一个来自编译器的抱怨:未报告的异常。那么,我能做些什么?

+0

@罗曼 - 你知道这笔交易。在不同的SO问题中提出不同的问题! – 2010-03-23 13:42:36

+0

Stephen C,我认为增加的部分也是“我应该如何从缓冲读取器读取?”的一部分。但我明白你的观点。我删除了添加的部分。 – Roman 2010-03-23 13:51:06

回答

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中的插座,乐于助人。

0

input阅读器连接到作为收听者的套接字,即保持收听传入的消息。

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

1

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

我建议使用IO函数围绕代码块包装try/catch并适当地处理错误。

0

但我不明白它是如何工作的。 ....等待,直到一些出现在 缓冲读取器和当一些 在那里出现,则返回true

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

0

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

0

如果这不是作业,你可能想看看Apache Commons IOUtils

假设你没有创建的BufferedReader,并只停留在为InputStream:

String results = IOUtils.toString(inputStream); 
System.out.println(results); 
0
while ((inputLine = input.readLine()) != null) { 

看那表情的每个部分:

input.readLine() 

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

inputLine = input.readLine() 

分配此字符串inputLine

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

检查该已分配的字符串不是空(流的终点)。

3

关于第一个问题:

但我不明白它是如何工作的。 inputLine = input.readLine()会等待,直到出现在缓冲读取器中的某个东西出现,并且当出现某些东西时,它会返回true,并执行循环中的代码。但是,当空值可以返回。

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

第二个问题:

上面的代码是从哪个抛出异常的方法取出并我在线程的运行方法中使用此代码。当我尝试抛出抛出异常之前运行编译器抱怨:重写的方法不会抛出异常。没有抛出异常,我有另一个抱怨来自编译器:未报告的异常。那么,我能做些什么?

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

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

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

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

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

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

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

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