我有以下从缓冲读取器读取的示例:
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
我还有另一个来自编译器的抱怨:未报告的异常。那么,我该怎么办?
答案 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)
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等),或使用编写良好的网络库,在这些较低级别的类上有很好的抽象(有几个开源的类)