简体   繁体   English

我应该如何从缓冲阅读器中读取?

[英]How should I read from a buffered reader?

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).每当缓冲读取器(在本例中为input中出现某些内容时,就会执行循环println的代码。 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. inputLine = input.readLine()等待直到缓冲读取器中出现某些东西,当某些东西出现在那里时,它返回true并执行循环中的代码。 But when null can be returned.但是什么时候可以返回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.上面的代码取自一个throws Exception的方法,我在线程的 run 方法中使用了这段代码。 And when I try to put throws Exception before the run the compiler complains: overridden method does not throw exception.当我尝试在run之前throws Exception ,编译器会抱怨:重写的方法不会抛出异常。 Without the throws exception I have another complain from the compiler: unreported exception.如果没有throws exception我还有另一个来自编译器的抱怨:未报告的异常。 So, what can I do?那么,我能做什么?

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 tutorial on reading/writing from/to a socket in Java, helpful.您可能会发现有关从/向 Java 套接字读取/写入的本教程很有帮助。

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. inputLine = input.readLine() 等待直到缓冲读取器中出现某些东西,当某些东西出现在那里时,它返回 true 并执行循环中的代码。 But when null can be returned.但是什么时候可以返回null。

BufferedReader.readLine() does not return true upon success. BufferedReader.readLine()在成功时不会返回true It returns a String containing the line that was read.它返回一个包含读取行的字符串。 If the end of the stream is reached, it returns null .如果到达流的末尾,则返回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.上面的代码取自一个抛出异常的方法,我在线程的 run 方法中使用了这段代码。 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.如果没有 throws 异常,我还有另一个来自编译器的抱怨:未报告的异常。 So, what can I do?那么,我能做什么?

You should wrap your code in a try/catch block .您应该将代码包装在try/catch 块中 If you don't want to handle the caught exception, simply leave that part blank (not recommended)如果您不想处理捕获的异常,只需将该部分留空(不推荐)

try {
    while ((inputLine = input.readLine()) != null) {
        System.out.println("I got a message from a client: " + inputLine);
    }
} catch (Exception e) {
    //handle exception
}

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 包裹在您的代码块中,并适当地处理错误。

input reader is connected to the socket, which is a listener, ie keeps listening to incoming messages. input阅读器连接到套接字,它是一个监听器,即不断监听传入的消息。

About your second question, you should put a try/catch block inside the method, catch the Exception and handle it.关于你的第二个问题,你应该在方法中放置一个 try/catch 块,捕获异常并处理它。 Do not re-throw it.不要重新扔掉它。

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.不,它返回表达式的值 (inputLine = input.readLine()),即 inputLine 本身。 The inputLine is compared to null. inputLine 与 null 进行比较。

null is returned when the "EOF (End Of File)" is reached.到达“EOF(文件结尾)”时返回 null。 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 之前,您可能会收到异常。

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);
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).检查分配的字符串是否为空(流结束)。

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.如果您需要将此传递给其他代码,但由于run()方法不允许任何检查异常而无法传递,您可以将异常包装在某种 RuntimeException 中。 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 方法直接在一个线程上执行(因为它可能是一个 Runnable),那么你应该小心重新抛出一个包装异常。

As for the result from readLine() , it will return null when there is nothing more to read.至于readLine()的结果,当没有更多可读取时,它将返回null 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 .我确实有一个警告,因为您将套接字包装在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.危险在于 BufferedReader 不能很好地处理读取过程中的异常。 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 .例如,查看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.它有一个公共变量,用于报告在最近的 I/O(读或写)请求中成功传输的字节数。 This means that the IO operation can be executed again to retrieve or send the remaining bytes for the packet.这意味着可以再次执行 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 等),或使用编写良好的网络库,对这些较低级别的类进行良好的抽象(有几个开源类可用)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Java中的缓冲读取器再次读取文件? - How do I read a file again using buffered reader in Java? 如何从缓冲读卡器中读取前五个字符? - How to read first five character from buffered reader? 从字符串缓冲的读取器读取所有行 - read all lines from string buffered reader 如何从缓冲读取器输入字符串? - How do i input a string from a buffered reader? 如何从缓冲的读取器文件中获取数字? - How can i get a number obtained from a buffered reader file? 通过限制读取的数据量从缓冲读取器读取 - Read from buffered reader by limiting the amount of data being read 如何有效地检查来自缓冲阅读器的读取行是否包含来自枚举列表的字符串 - How to efficiently check if read line from Buffered reader contains a string from an enum list 如何使用缓冲读取器仅读取文本或txt文件中的数字? - How do I use Buffered Reader to read only text, or only numbers in a txt file? 如何使用扫描仪或缓冲读取器读取输入文件,并计算输入文件中特定字符的所有出现次数 - How do I read in an input file with a scanner or buffered reader and count all the occurences of a specific character in the input file 如何使缓冲的读取器从头开始读取,而不是使用另一个对象 - how to make a buffered reader read from the beginning instead of using another object
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM