开发者

Can't exit while loop in Java when extracting lines from BufferedReader

开发者 https://www.devze.com 2023-03-06 01:44 出处:网络
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 exec

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 los开发者_C百科t 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


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.


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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消