Java 我应该如何从缓冲阅读器中读取?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2500107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How should I read from a buffered reader?
提问by Roman
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.
println
每当缓冲读取器中出现某些内容(input
在本例中)时,就会执行循环中的代码。就我而言,如果客户端应用程序向套接字写入内容,则将执行循环中(在服务器应用程序中)的代码。
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.
但我不明白它是如何工作的。inputLine = input.readLine()
等待直到缓冲读取器中出现某些东西,当某些东西出现在那里时,它返回true
并执行循环中的代码。但是什么时候null
可以退货。
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?
还有一个问题。上面的代码取自一个方法,throws Exception
我在 Thread 的 run 方法中使用了这段代码。当我尝试在编译器抱怨throws Exception
之前放置时run
:重写的方法不会抛出异常。没有throws exception
我有另一个来自编译器的抱怨:未报告的异常。那么,我能做什么?
采纳答案by tvanfosson
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.
当另一端的套接字关闭时,读取器应返回一个空字符串。这是您正在寻找的条件。要处理异常,请将读取循环包装在 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);
}
You might find this tutorialon reading/writing from/to a socket in Java, helpful.
您可能会发现这个关于从/向 Java 套接字读取/写入的教程很有帮助。
回答by medopal
input
reader is connected to the socket, which is a listener, i.e. keeps listening to incoming messages.
input
reader 连接到套接字,它是一个侦听器,即不断侦听传入的消息。
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.
关于你的第二个问题,你应该在方法中放置一个 try/catch 块,捕获异常并处理它。不要重新扔掉它。
回答by Bryan Denny
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.
读取器的 readLine() 将在读取某些内容时返回一个字符串值,在没有任何内容时返回一个空字符串,并在连接关闭时返回 null。
I would recommend wrapping a try/catch around your block of code with the IO function and handle errors appropriately.
我建议使用 IO 函数在代码块周围包裹一个 try/catch 并适当地处理错误。
回答by PeterMmm
But I do not understand how it works. .... waits until something appears in the buffered reader and when something appears there it returns true
但我不明白它是如何工作的。.... 等到缓冲读取器中出现某些东西,当某些东西出现在那里时,它返回 true
No, it returns the value of the expression (inputLine = input.readLine()), the inputLine itself. The inputLine is compared to null.
不,它返回表达式的值 (inputLine = input.readLine()),即 inputLine 本身。inputLine 与 null 进行比较。
回答by M. Jessup
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.
到达“EOF(文件结尾)”时返回 null。由于这是从网络套接字读取,因此在套接字断开连接时(由服务器或客户端)创建文件结尾,但您可能会在实际看到 EOF 之前收到异常。
回答by Dean J
If this isn't for homework, you might want to look at Apache Commons IOUtils.
如果这不是家庭作业,您可能需要查看 Apache Commons IOUtils。
Assuming you don't create the BufferedReader, and just stop at the InputStream:
假设您不创建 BufferedReader,而只是在 InputStream 处停止:
String results = IOUtils.toString(inputStream);
System.out.println(results);
回答by fgb
while ((inputLine = input.readLine()) != null) {
Look at each part of the expression:
查看表达式的每个部分:
input.readLine()
Returns a String which will be null if the end of the stream has been reached (or throws an Exception on error).
返回一个字符串,如果已到达流的末尾(或在错误时抛出异常),该字符串将为 null。
inputLine = input.readLine()
Assigns this String to inputLine
将此字符串分配给 inputLine
((inputLine = input.readLine()) != null)
Checks that the String that was assigned is not null (end of stream).
检查分配的字符串是否为空(流结束)。
回答by Peter Di Cecco
For your first question:
对于你的第一个问题:
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.
但我不明白它是如何工作的。inputLine = input.readLine() 等待直到缓冲读取器中出现某些东西,当某些东西出现在那里时,它返回 true 并执行循环中的代码。但是什么时候可以返回null。
BufferedReader.readLine()
does not return true
upon success. It returns a String containing the line that was read. If the end of the stream is reached, it returns null
.
BufferedReader.readLine()
true
成功后不会返回。它返回一个包含读取行的字符串。如果到达流的末尾,则返回null
。
Your second 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?
上面的代码取自一个抛出异常的方法,我在线程的 run 方法中使用了这段代码。当我尝试在运行之前抛出异常时,编译器会抱怨:重写的方法不会抛出异常。如果没有 throws 异常,我还有另一个来自编译器的抱怨:未报告的异常。那么,我能做什么?
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)
您应该将代码包装在try/catch 块中。如果您不想处理捕获的异常,只需将该部分留空(不推荐)
try {
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
} catch (Exception e) {
//handle exception
}
回答by Kevin Brock
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.
你已经收到了一些很好的答案。只需捕获异常并在本地处理即可。如果您需要将此传递给其他代码,但由于该run()
方法不允许任何检查异常而无法传递,您可以将异常包装在某种 RuntimeException 中。如果 run 方法直接在一个线程上执行(因为它可能是一个 Runnable),那么你应该小心重新抛出一个包装异常。
As for the result from readLine()
, it will return null
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).
至于来自 的结果readLine()
,它会null
在没有什么可读取的时候返回。在套接字的情况下,这是另一方干净地关闭套接字时(任何突然终止或不干净的关闭通常会导致您的代码异常,因为操作系统将发送不同类型的套接字关闭通知)。
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.
我确实有一个警告,因为您将套接字包装在java.io.BufferedReader
. 在任何类型的生产代码中使用它时都应该非常小心。
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.
危险在于 BufferedReader 不能很好地处理读取过程中的异常。如果您在套接字上启用了超时,则这尤其是一个问题,因此代码将自动从操作系统接收定期异常。当读取器内的缓冲区正在填充时,可能会出现超时(或其他异常)。如果您尝试在异常之后重用该对象,它将忽略缓冲区中的任何先前内容。先前收到的数据包会悄悄丢失,并且无法检索这些字节。
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.
请注意,还有其他类型的套接字异常并不意味着套接字已丢失。例如,看看 的定义java.io.InterruptedIOException
。它有一个公共变量,用于报告在最近的 I/O(读或写)请求中成功传输的字节数。这意味着可以再次执行 IO 操作以检索或发送数据包的剩余字节。
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).
从套接字读取的正确方法是直接使用套接字流,使用 NIO(ByteBuffers 等),或使用编写良好的网络库,对这些较低级别的类进行良好的抽象(有几个开源类可用)。