Search code examples
javanewlineinputstreambufferedreadereol

why does BufferedReader fail to read the final line for an InputStream?


*Note: To clarify, maybe this question wasn't quite clear on the InputStream being "alive." The connection to the telnet weather service (see below for link) is kept open. The goal is to get all lines coming from the server.*

Building from the sample Apache WeatherTelnet code, I'm using InputStream.read to output the server results (inspired by a javamex tutorial idiom) one char at a time, using the chars method:

thufir@dur:~$ 
thufir@dur:~$ java -jar NetBeansProjects/Teln/dist/Teln.jar 
------------------------------------------------------------------------------
*               Welcome to THE WEATHER UNDERGROUND telnet service!            *
------------------------------------------------------------------------------
*                                                                            *
*   National Weather Service information provided by Alden Electronics, Inc. *
*    and updated each minute as reports come in over our data feed.          *
*                                                                            *
*   **Note: If you cannot get past this opening screen, you must use a       *
*   different version of the "telnet" program--some of the ones for IBM      *
*   compatible PC's have a bug that prevents proper connection.              *
*                                                                            *
*           comments: jmasters@wunderground.com                              *
------------------------------------------------------------------------------

Press Return to continue:
^Cthufir@dur:~$ 

which is the desired output. However, reading the InputStream with a BufferedReader results in dropping the last line. (Or, at least, it's not printed to the console.) Bad output, using lines method:

thufir@dur:~$ 
thufir@dur:~$ java -jar NetBeansProjects/Teln/dist/Teln.jar 

------------------------------------------------------------------------------

*               Welcome to THE WEATHER UNDERGROUND telnet service!            *

------------------------------------------------------------------------------

*                                                                            *

*   National Weather Service information provided by Alden Electronics, Inc. *

*    and updated each minute as reports come in over our data feed.          *

*                                                                            *

*   **Note: If you cannot get past this opening screen, you must use a       *

*   different version of the "telnet" program--some of the ones for IBM      *

*   compatible PC's have a bug that prevents proper connection.              *

*                                                                            *

*           comments: jmasters@wunderground.com                              *

------------------------------------------------------------------------------



^Cthufir@dur:~$ 
thufir@dur:~$ 

StreamReadercode:

package teln;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamReader {

    private StreamReader() {
    }

    StreamReader(InputStream inputStream) throws IOException {
        lines(inputStream);
    }

    private void chars(InputStream inputStream) throws IOException {
        do {
            char ch = (char) inputStream.read();
            System.out.print(ch);
        } while (true);
    }

    private void lines(InputStream inputStream) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        String line = "";
        do {
            System.out.println(line);
        } while ((line = br.readLine()) != null);

        System.out.println(line);

    }
}

Presumably that last line is "null" somehow? Can the logic be altered so that the final line is printed from within lines just as it is from chars?


Solution

  • A BufferedReader#readLine() reads the stream until it reaches either \n, \r, or the end of the stream, returning what it read up to then or null. You're not showing us something. Why are there new lines between lines in your output?

    As for the null at the end of your output

    private void lines(InputStream inputStream) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        String line = "";
        do {
            System.out.println(line); // will print an empty line to start
        } while ((line = br.readLine()) != null);
    
        System.out.println(line); // will print null
    
    }
    

    Your loop should be

    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
    

    to avoid printing the first empty one. Also, don't print the line outside the while loop. It will always be null, obviously (you wouldn't be outside the while otherwise).

    Your chars() method is also looping forever.

    It's very possible your server isn't closing the stream and so the underlying read calls that the BufferedReader makes aren't returning -1 to indicate EOF. Are you killing the application yourself?