以下代码在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();
stracktrace:
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 ??
中有什么变化答案 0 :(得分:9)
我也注意到了这一点。您可以做的一件事是在循环结束时检查BufferedReader的状态:
while((line = rd.readLine()) != null){
sb.append(line);
if (!rd.ready()) {
break;
}
}
rd.close();
但是, ready()并不能保证您的信息流在最后。它仅检查流是否被阻止或关闭。 见BufferedReader.ready() on developer.android.com
我认为这是Android OS 2.3及更高版本中引入的错误。请在官方安卓网站上为bug基础做出贡献,以鼓励谷歌解决这个问题。不幸的是,已经有很多设备已经附带OS版本2.3到2.3.3。
您的情况是,您可能在一次读取中命中了文件的末尾,并且流会自动关闭。我认为这是Android 2.3及更高版本中引入的错误。
glassonion的帖子可行,但该解决方法对长数据流的执行速度非常慢。
由于移动应用程序可能随时丢失互联网连接,因此您正在读取的InputStream可能只是被阻止并等待更多数据。
更合适的方法可能是在新线程上打开套接字,读取数据并等待超时以避免连接缓慢。
The following article解释了很好地处理停滞不前的连接。阅读摘要应该足以说服你。
所有优秀的网络应用程序都将包括超时检测和处理。无论您是在编写客户端,还是需要检测任意服务器,或者编写服务器并且需要防止连接失效,超时处理都是错误处理的关键部分。
答案 1 :(得分: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();