5

以下代码在 Android 1.5-2.2.1 中运行良好,但不适用于 2.3 及更高版本。

BufferedReader rd;
rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));

StringBuffer sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null){
    sb.append(line);
}
rd.close();

轨迹:

01-30 08:21:42.668: WARN/System.err(594): java.io.IOException: BufferedInputStream is closed
01-30 08:21:42.668: WARN/System.err(594):     at java.io.BufferedInputStream.streamClosed(BufferedInputStream.java:116)
01-30 08:21:42.728: WARN/System.err(594):     at java.io.BufferedInputStream.read(BufferedInputStream.java:274)
01-30 08:21:42.728: WARN/System.err(594):     at org.apache.harmony.luni.internal.net.www.protocol.http.UnknownLengthHttpInputStream.read(UnknownLengthHttpInputStream.java:40)
01-30 08:21:42.758: WARN/System.err(594):     at java.io.InputStreamReader.read(InputStreamReader.java:255)
01-30 08:21:42.758: WARN/System.err(594):     at java.io.BufferedReader.fillBuf(BufferedReader.java:128)
01-30 08:21:42.758: WARN/System.err(594):     at java.io.BufferedReader.readLine(BufferedReader.java:357)

这是一个问题吗?2.3有什么变化吗?

4

2 回答 2

9

我也注意到了这一点。您可以做的一件事是在循环结束时检查 BufferedReader 的状态:

while((line = rd.readLine()) != null){
    sb.append(line);
    if (!rd.ready()) {
       break;
    }
}
rd.close();

但是,ready()并不能保证您的流在末尾。它只检查流是否被阻塞或关闭。请参阅developer.android.com 上的 BufferedReader.ready()

我认为这是 Android OS 2.3 及更高版本中引入的错误。请在官方 android 网站上贡献 bug 库,以鼓励 Google 修复此问题。不幸的是,已经有许多设备附带了 OS 版本 2.3 到 2.3.3。

您的情况是您可能已经在一次读取中到达文件末尾并且流自动关闭。我认为这是 Android 2.3 及更高版本中引入的错误。

glassonion 的帖子会起作用,但这种解决方法在长数据流上的执行速度会非常缓慢。

由于移动应用程序可能随时失去互联网连接,因此您正在读取的 InputStream 可能只是被阻止并等待更多数据。

更合适的方法可能是在新线程上打开一个套接字,读取数据并等待超时以对冲连接中的任何缓慢。

以下文章很好地解释了处理停滞的连接。阅读摘要应该足以说服您。

All good network applications will include timeout detection and handling. Whether you're writing a client, and need to detect a wayward server, or writing a server and need to prevent stalled connections, timeout handling is a critical part of error handling.

于 2011-03-04T07:20:53.043 回答
2

解决方法如下。

InputStreamReader sr;
sr = new InputStreamReader(connection.getInputStream(), "UTF-8");
StringBuilder builder = new StringBuilder();
for (int bt = 0; (bt = sr.read()) != -1;) {
  builder.append((char)bt);
}
sr.close();
于 2011-03-04T06:38:15.327 回答