从 BufferedReader 中提取行时无法退出 Java 中的 while 循环

发布于 2024-11-06 17:47:40 字数 637 浏览 4 评论 0原文

我正在尝试使用 while 循环从 java 中的 BufferedReader 读取行。它将按预期遍历 BufferedReader,但当它从循环中中断时,它将“冻结”代码的执行。我尝试调试代码,但执行提示在循环后丢失。不知道我做错了什么:

代码片段:

BufferedReader reader = new BufferedReader(new  InputStreamReader(yourSocket.getInputStream()));
String nextLine = null;

nextLine = reader.readLine();
while (nextLine != null){ //print all of input stream
    System.out.println(nextLine);
    nextLine = reader.readLine();
}

我假设当 BufferedReader 中没有剩余行时,nextLine 变量将返回 null 并中断循环。我尝试过手动打破循环,但似乎也不起作用。同样,代码可以很好地打印 BufferedReader 的行,但 while 循环后面的任何代码不一定会运行。

如果此信息还不够,请告诉我。如果需要的话我也可以过去完整的代码。

谢谢, 拍

I'm trying to read lines from a BufferedReader in java by using a while loop. It will traverse through the BufferedReader as should, but when it should break from the loop it will 'freeze' the execution of the code. I've tried debugging the code but it the execution cue is lost after the loop. No idea what I'm doing wrong:

Code snippet:

BufferedReader reader = new BufferedReader(new  InputStreamReader(yourSocket.getInputStream()));
String nextLine = null;

nextLine = reader.readLine();
while (nextLine != null){ //print all of input stream
    System.out.println(nextLine);
    nextLine = reader.readLine();
}

I've assumed that when there are no lines left in the BufferedReader that the nextLine variable would return null and break the loop. I've tried breaking the loop manually but it doesn't seem to work neither. Again, the code would print the BufferedReader's lines fine but any code following the while loop will not necessarily run.

If this info is not enough, please let me know. I can also past the full code if necessary.

Thanks,
Pat

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

疧_╮線 2024-11-13 17:47:40

从套接字读取是一个阻塞调用。您的程序不知道另一端已完成对套接字的写入。您通常必须使用一些标记或大小信息来标识另一端的程序已完成对套接字的写入。一旦你读取了该标记,你就退出循环。此行为与读取文件不同 - 当到达文件末尾时,调用 readLine() 方法时会返回 null,并且可以像示例中那样退出。

Reading from sockets is a blocking call. Your program does not know the fact that other side has finished writing to the socket. You will typically have to use some markers or size information to identify the program on the other end has finished writing to the socket. Once you read that marker you exit from the loop. This behavior is different from reading say files- when you reach the end of file, you get a null back when the readLine() method is called and you can exit as you do in your example.

路还长,别太狂 2024-11-13 17:47:40

问题似乎是您的Reader包裹在阻塞的Socket中,这不会指示流结束 em> 直到对方关闭连接(或者你方关闭连接)。您可能已经阅读了所有可用的内容,但是当您尝试阅读更多内容时,底层的 InputStream 会阻止尝试从套接字读取更多数据。

当某些数据最终变得可用时,InputStream 会将这些数据提供给 Reader,并且一旦 Reader 看到足够的数据以构成一个完整的一行 - 或流结束 - 您将从Reader中返回最后一行。尝试读取下一行最终将返回 null。

The problem appears to be that your Reader is wrapped around a blocking Socket, which will not indicate end-of-stream until the peer closes the connection (or your side closes the connection). You may have read all that's available, but when you try to read more, the underlying InputStream blocks trying to read more data from the socket.

When some data eventually becomes available, the InputStream will make that data available to the Reader, and, once the Reader has seen enough to constitute a complete line—or end-of-stream—you'll get your last line back out of the Reader. Trying to read the next line would finally return null.

箹锭⒈辈孓 2024-11-13 17:47:40

我刚刚回复了别人的帖子,就这个问题。 我的作弊方法解决了这个问题。

使用像你这样的循环...

String line;
while ((line = in.readLine()) != null) {
    System.out.println(line);
    sleep(in);
    if(!in.ready()){
        break;
    }
}

我想出了一种作弊方法。

private static void sleep(BufferedReader in) throws IOException {
    long time = System.currentTimeMillis();
    while(System.currentTimeMillis()-time < 1000){
        if(in.ready()){
            break;
        }
    }       
}

这可能很草率,但如果您创建一个等待一定时间的 sleep 方法,并继续检查 BufferedReader 是否“准备好”。如果是的话,你可以突破,但当你出来时再检查一下。 -- 也许您可以只返回一个布尔值而不是检查两次,但概念就在那里。

I just answered someone else's post about this. My cheater way around this.

Using a loop like you are...

String line;
while ((line = in.readLine()) != null) {
    System.out.println(line);
    sleep(in);
    if(!in.ready()){
        break;
    }
}

There is a cheater way that I figured out.

private static void sleep(BufferedReader in) throws IOException {
    long time = System.currentTimeMillis();
    while(System.currentTimeMillis()-time < 1000){
        if(in.ready()){
            break;
        }
    }       
}

This might be sloppy, but if you make a sleep method that waits an amount of time and just keep checking if the BufferedReader is "ready." If it is, you can break out, but then when you come out check again. -- Maybe you could just return a boolean instead of checking twice, but the concept is there.

不打扰别人 2024-11-13 17:47:40

我自己编写了一些类似的代码来探索如何在 Java 中处理 HTTP 请求,我不相信 BufferedReader 的行为与从用于传输 HTTP 请求的 Socket 读取数据兼容,因为正如这里已经提到的, readLine() 会阻塞如果没有更多数据可供读取,则您的应用程序将挂起。根据 HTTP 规范,客户端在写入请求后保持套接字打开,因此 readLine() 只是等待,直到有更多可用数据。尝试检测 HTTP 请求最后一行的尾随 \n\r 在 readLine() 返回的行上也不起作用,因为它会去除任何行尾字符组合:\n、\r 或 \r\名词

请求的标头和正文之间还包含一个空行,因此,如果您要查找空行作为消息的终止,则需要检查它不是标头和正文之间的行。

我认为使用 read(byte[]) 从 InputStream 中逐个字符读取是实现此目的的方法 - 它将读取到 byte[] 的大小,并在遇到流末尾时终止读取。

Having written some similar code myself to explore how to handle HTTP requests in Java, I don't believe the behavior of the BufferedReader is compatible with reading from a Socket being used to transfer HTTP requests, because as already mentioned here, readLine() blocks if there's no more data to be read, therefore your app hangs. Per the HTTP spec the client keeps the Socket open after it has written its request, so readLine() just waits until there's more data available. Trying to detect the trailing \n\r on the last line of the HTTP request also doesn't work on a line returned from readLine() because it strips any end of line character combination: \n, \r, or \r\n.

A blank line is also included between the headers and the body of a request, so if you're looking for a blank line as the termination of the message, you need to check it's not the line between the headers and body.

I think reading character by character from the InputStream with read(byte[]) is the way to go for this - it will read up to the size of your byte[], and terminates reading if encounters end of stream.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文