我应该如何从缓冲阅读器中读取内容?
我有以下从缓冲读取器读取的示例:
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
只要缓冲读取器中出现某些内容(在本例中为 input
),循环 println
中的代码就会被执行。就我而言,如果客户端应用程序向套接字写入某些内容,则循环(在服务器应用程序中)中的代码将被执行。
但我不明白它是如何工作的。 inputLine = input.readLine()
等待直到缓冲读取器中出现某些内容,当其中出现某些内容时,它返回 true
并执行循环中的代码。但是当null
时可以返回。
还有一个问题。上面的代码取自一个抛出异常
的方法,我在线程的 run 方法中使用了这段代码。当我尝试在运行之前放置抛出异常时,编译器会抱怨:重写的方法不会抛出异常。如果没有抛出异常
,我还会收到编译器的另一个抱怨:未报告的异常。那么,我能做什么呢?
I have the following example of reading from a buffered reader:
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
The code in the loop println
will be executed whenever something appears in the buffered reader (input
in this case). In my case, if a client-application writes something to the socket, the code in the loop (in the server-application) will be executed.
But I do not understand how it works. inputLine = input.readLine()
waits until something appears in the buffered reader and when something appears there it returns true
and the code in the loop is executed. But when null
can be returned.
There is another question. The above code was taken from a method which throws Exception
and I use this code in the run method of the Thread. And when I try to put throws Exception
before the run
the compiler complains: overridden method does not throw exception. Without the throws exception
I have another complain from the compiler: unreported exception. So, what can I do?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
当另一端的套接字关闭时,读取器应返回空字符串。这就是您正在寻找的条件。要处理异常,请将读取循环包装在 try/catch 块中。
您可能会发现这个关于读取/写入的教程到 Java 中的套接字,很有帮助。
When the socket on the other end is closed, the reader should return a null string. This is the condition that you are looking for. To handle the exception, wrap the reading loop in a try/catch block.
You might find this tutorial on reading/writing from/to a socket in Java, helpful.
对于你的第一个问题:
BufferedReader.readLine ()
成功时不会返回true
。它返回一个包含已读取行的字符串。如果到达流末尾,则返回null
。您的第二个问题:
您应该将代码包装在 try/catch 块中。如果您不想处理捕获的异常,只需将该部分留空即可(不推荐)
For your first question:
BufferedReader.readLine()
does not returntrue
upon success. It returns a String containing the line that was read. If the end of the stream is reached, it returnsnull
.Your second question:
You should wrap your code in a try/catch block. If you don't want to handle the caught exception, simply leave that part blank (not recommended)
当读取器读取到某些内容时,读取器的 readLine() 将返回一个字符串值;当还没有读取任何内容时,将返回一个空字符串;当连接关闭时,将返回 null。
我建议使用 IO 函数在代码块周围包装一个 try/catch 并适当地处理错误。
The reader's readLine() will return a string value when it has something read, an empty string when there isn't anything yet, and null when the connection is closed.
I would recommend wrapping a try/catch around your block of code with the IO function and handle errors appropriately.
input
reader 连接到套接字,它是一个侦听器,即不断侦听传入的消息。关于你的第二个问题,你应该在方法中放置一个 try/catch 块,捕获异常并处理它。不要重新扔掉它。
input
reader is connected to the socket, which is a listener, i.e. keeps listening to incoming messages.About your second question, you should put a try/catch block inside the method, catch the Exception and handle it. Do not re-throw it.
否,它返回表达式 (inputLine = input.readLine()) 的值,即 inputLine 本身。 inputLine 与 null 进行比较。
No, it returns the value of the expression (inputLine = input.readLine()), the inputLine itself. The inputLine is compared to null.
当到达“EOF(文件结束)”时,返回 null。由于这是从网络套接字读取,因此当套接字断开连接(由服务器或客户端)时创建文件结尾,但在实际看到 EOF 之前您可能会收到异常。
null is returned when the "EOF (End Of File)" is reached. Since this is reading from a network socket, the end of file is created when the socket is disconnected (either by the server or the client), but you will likely get an Exception before you actually see the EOF.
如果这不是为了家庭作业,您可能需要查看 Apache Commons IOUtils。
假设您不创建 BufferedReader,只是停在 InputStream 处:
If this isn't for homework, you might want to look at Apache Commons IOUtils.
Assuming you don't create the BufferedReader, and just stop at the InputStream:
查看表达式的每个部分:
如果已到达流末尾,则返回一个 String,该 String 将为 null(或在错误时抛出异常)。
将此字符串分配给 inputLine
检查分配的字符串是否不为 null(流末尾)。
Look at each part of the expression:
Returns a String which will be null if the end of the stream has been reached (or throws an Exception on error).
Assigns this String to inputLine
Checks that the String that was assigned is not null (end of stream).
您已经收到了一些很好的答案。只需捕获异常并在本地处理即可。如果您需要将此传递给其他代码,但由于
run()
方法不允许任何检查异常而无法传递,则可以将该异常包装在某种 RuntimeException 中。如果 run 方法直接在线程上执行(因为它可能是 Runnable),那么您应该小心重新抛出包装的异常。至于
readLine()
的结果,当没有更多内容可读取时,它将返回null
。对于套接字,这是指另一方干净地关闭套接字(任何突然终止或不干净的关闭通常都会导致代码中出现异常,因为操作系统将发送不同类型的套接字关闭通知)。由于您将套接字包装在
java.io.BufferedReader
中,因此我确实有一句话要小心。在任何类型的生产代码中使用它时都应该非常小心。危险在于 BufferedReader 不能很好地处理读取过程中的异常。如果您在套接字上启用了超时,则这尤其是一个问题,因此代码将自动从操作系统接收定期异常。当读取器内的缓冲区正在填充时,可能会出现超时(或其他异常)。如果您尝试在异常发生后重用该对象,它将忽略缓冲区中任何先前的内容。先前收到的数据包会默默丢失,并且无法检索这些字节。
请注意,还有其他类型的套接字异常并不意味着套接字已丢失。例如,查看 java.io.InterruptedIOException 的定义。它有一个公共变量,用于报告最近 I/O(读或写)请求中成功传输的字节数。这意味着可以再次执行 IO 操作以检索或发送数据包的剩余字节。
如果出现任何异常,您的设计是立即关闭读取器和套接字,则该方法将正常工作。
从套接字读取数据的正确方法是直接使用套接字流,使用 NIO(ByteBuffer 等),或者使用编写良好的网络库,对这些较低级别的类进行良好的抽象(有几个可用的开源库)。
You have received some good answers. Just catch the exception and deal with it locally. If you need to pass this on to other code but cannot since the
run()
method does not allow for any check exception, you can wrap the exception in a RuntimeException of some kind. If the run method is executing directly on a Thread (since it is a Runnable probably) then you should take care with re-throwing a wrapped exception.As for the result from
readLine()
, it will returnnull
when there is nothing more to read. In the case of a socket this is when the other side cleanly closes the socket (any sudden termination or unclean close would typically result in an exception in your code as the OS will send a different kind of socket close notification).I do have one word of caution since you are wrapping a socket in a
java.io.BufferedReader
. You should be very careful about using this in any kind of production code.The danger is that BufferedReader does not deal well with exceptions in the midst of reading. This is especially an issue if you have enabled a timeout on the socket so the code will receive periodic exceptions automatically from the operating system. The timeout (or other exception) could come while the buffer inside the reader is filling. If you attempt to reuse the object after the exception, it will ignore any previous contents in the buffer. The packet(s) that were previously received are silently lost and there is no way to retrieve those bytes.
Note that there are other kinds of socket exceptions that do not mean that the socket has been lost. For instance, look at the definition of
java.io.InterruptedIOException
. This has a public variable that reports the number of bytes successfully transferred in the most recent I/O (read or write) request. This means that the IO operation can be executed again to retrieve or send the remaining bytes for the packet.If upon any exception your design is to immediately close the reader and socket the method will work correctly.
The proper way to read from a socket is to use the socket stream directly, use NIO (ByteBuffers and such), or use a well written network library with good abstractions over these lower level classes (several open source ones are available).