为什么BufferedReader无法读取InputStream的最后一行?

时间:2013-08-29 18:14:53

标签: java newline inputstream bufferedreader eol

*注意:为了澄清,也许这个问题在InputStream“活着”时并不十分清楚。与telnet气象服务的连接(见下面的链接)保持打开状态。目标是获取来自服务器的所有行。*

从示例Apache WeatherTelnet code构建,我使用InputStream.read一次输出一个字符的服务器结果(灵感来自javamex tutorial成语),使用chars方法:

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:~$ 

这是所需的输出。但是,使用InputStream阅读BufferedReader会导致删除最后一行。 (或者,至少,它没有打印到控制台。)输出错误,使用lines方法:

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:~$ 

StreamReader代码:

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);

    }
}

据推测,最后一行是“null”?是否可以更改逻辑,以便从lines开始在chars内打印最后一行?

4 个答案:

答案 0 :(得分:4)

您还没有解释数据的来源,但我怀疑它来自某些来源并且没有关闭流。< / p>

如果流已关闭 - 例如通过终止连接,如果这是一个客户端/服务器应用程序 - 那么你看到最后一行。 BufferedReader肯定会返回最后一行数据,即使它没有以行终止符结束,但只有当知道时它才会到达流的末尾。

答案 1 :(得分:2)

正如Jean所提到的,如果你知道你的输入永远不会以换行'\n'或回车'\r'字符结束,那么这就是使用BufferReader的一个缺点。在while循环后,您可能需要使用ready()方法来测试最后一行读取后是否确实有更多文本,并使用其中一种read()方法来提取其余内容文本。或者,将另一个文本阅读器替换为BufferReader。

答案 2 :(得分:2)

BufferedReader#readLine()读取流,直到它到达\n\r或流的末尾,然后返回它读取的内容或null。你没有向我们展示一些东西。为什么输出中的行之间有新行?

至于输出结尾处的null

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

}

你的循环应该是

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

避免打印第一个空的。另外,请勿在{{1​​}}循环外打印line。它总是while,显然(你不会超出null)。

您的while方法也会永远循环播放。

您的服务器很可能没有关闭流,因此chars()所做的基础read调用不会返回BufferedReader来指示EOF。你自己杀了这个应用程序吗?

答案 3 :(得分:0)

好的,这就是kludge:

package teln;

import static java.lang.System.out;
import java.io.IOException;
import java.io.InputStream;

public class StreamReader {

    private StreamReader() {
    }

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

    private void printEachLine(InputStream inputStream) throws IOException {
        int foo = 0;
        char ch = 0;
        StringBuilder sb = new StringBuilder();
        out.println("lines..");
        boolean isEOL = false;  //err, need to set this or get rid of it
        do {
            foo = inputStream.read();
            ch = (char) foo;
            //out.print(foo);
            sb.append(ch);
            if ((ch == 10)) {
                out.print(sb);
                sb = new StringBuilder();
                foo = inputStream.read();
                ch = (char) foo;
                sb.append(ch);
                if (ch != 13) {
                    while ((255 > ch) && (ch >= 0)) {
                        sb = new StringBuilder();
                        foo = inputStream.read();
                        ch = (char) foo;
                        sb.append(ch);
                        out.print(sb);
                    }
                }
                sb.append(ch);
            }

        } while (!isEOL);

    }
}

这取决于特定模式后的LF和CR。除非是第一行或最后一行,否则LF,10总是跟随CR,13。因此,在这种特殊情况下,此代码将查找缺少的CR并将其识别为需要特殊输出。

然而,这是一个巨大的假设,可能是特定于这个天气telnet服务。而且,看起来非常脆弱。

现在,我会继续这样做,但会继续寻找另一个答案。