[英]why does BufferedReader fail to read the final line for an InputStream?
*注意:為澄清起見,也許這個問題在InputStream處於“活動狀態”時還不清楚。 與telnet氣象服務的連接(請參閱下面的鏈接)保持打開狀態。 目標是讓所有線路都來自服務器。*
從示例Apache WeatherTelnet
代碼構建,我正在使用InputStream.read來使用chars
方法一次輸出一個字符(一個javamex教程習慣的啟發)的服務器結果:
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:~$
這是所需的輸出。 但是,使用BufferedReader
讀取InputStream
導致刪除最后一行。 (或者,至少,它沒有打印到控制台。)輸出錯誤,使用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);
}
}
大概最后一行是“空”嗎? 可以更改邏輯,以便從lines
像在chars
一樣打印最后一行嗎?
您還沒有解釋數據的來源,但是我懷疑數據來自某些來源,這些來源的末尾沒有行終止符, 也沒有關閉流 。
如果關閉了流(例如,通過終止連接,如果這是客戶端/服務器應用程序), 則將看到最后一行。 BufferedReader
肯定會返回最后一行數據,即使它沒有以行終止符結尾,也只有在知道它已經到達流的末尾時才返回。
正如Jean所提到的,如果您知道輸入永遠不會以換行符'\\n'
或回車符'\\r'
結束,則使用BufferReader是一個缺點。 在while
循環之后while
您可能需要使用ready()
方法來測試在最后一行讀取之后是否確實還有更多文本,並使用read()
方法之一來提取剩余的文本。 或者,將另一個文本閱讀器全部替換為BufferReader。
BufferedReader#readLine()
讀取流,直到它到達\\n
, \\r
或流的末尾,返回它所讀取的內容,然后返回null
或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);
}
避免打印第一個空的。 另外,不要在while
循環外打印該line
。 這將永遠是null
,顯然(你不會是外面while
其他)。
您的chars()
方法也將永遠循環。
您的服務器很有可能沒有關閉流,因此BufferedReader
進行的基礎read
調用不會返回-1
來表示EOF。 您是在自行殺死應用程序嗎?
好的,這里出現了kudge:
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服務。 此外,似乎非常脆弱。
現在,我將繼續講下去,但將繼續尋找其他答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.