2

*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?

4

4 回答 4

4

您还没有解释数据的来源,但我怀疑它来自某个在末尾没有行终止符并且没有关闭流的来源

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

于 2013-08-29T18:57:06.533 回答
3

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

于 2013-08-29T18:30:36.387 回答
2

ABufferedReader#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);
}

以避免打印第一个空的。另外,不要打印循环line外部。while显然,它将永远是null(您不会在while其他情况下)。

你的chars()方法也永远循环。

您的服务器很可能没有关闭流,因此进行的底层read调用BufferedReader没有返回-1以指示 EOF。您是在自己杀死应用程序吗?

于 2013-08-29T18:42:08.737 回答
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 服务。而且,看起来非常脆弱。

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

于 2013-08-29T22:18:49.957 回答