0

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

3
  • Where did you get the reader from? Commented May 13, 2011 at 0:38
  • What protocol is exchanged over the socket? Does the server side of the socket ever close its stream? Commented May 13, 2011 at 0:42
  • your socket is a Socket. I've tried to copy the code from another forum as I'm trying to treat an HTTP request. I'm going to assume that the socket doesn't close the stream. Problem is that by closing the stream I lose the read functionality on the BufferedReader. Commented May 13, 2011 at 0:55

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

2 Comments

This makes sense. Abit of context: I'm trying to handle an HTTP request through a socket's input stream, then read every line of the HTTP request. What I've noticed is that when I send a second HTTP request (by refreshing my web browser sending the request), the execution will continue on my code, indicating that the stream is closed when refreshing. Now the question is, is there a better way of trying to handle the inputStream than placing it into a BufferedReader, or is there a way of manually closing the stream without any ill effets to the HTTP communcations?
The delegating streams defined in the Java library close their delegate upon a call to close(), which can be annoying to work around. In your case, if you close the outermost BufferedReader, it will close the InputStreamReader, which will close the InputStream provided by the socket, which will close the socket, per the documentation for Socket#getInputStream(). You need to study how HTTP expresses the framing of its message. See RFC 2616 section 4.4 to learn how to determine how to read the message to completion (and no further).
1

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.