问题
The following code is working fine in Android 1.5-2.2.1 but it's not in 2.3 and higher.
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();
The 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)
Is this an issue? Has anything changed in 2.3??
回答1:
I noticed this as well. One thing you can do is check the state of the BufferedReader at the end of your loop:
while((line = rd.readLine()) != null){
sb.append(line);
if (!rd.ready()) {
break;
}
}
rd.close();
However, ready() does not guarantee that your stream is at the end. It only checks if the stream is blocked or closed. See BufferedReader.ready() on developer.android.com
I think this is a bug introduced in Android OS 2.3 and above. Please contribute to the bug base on the the official android site to encourage Google to fix this problem. Unfortunately, there are already many devices that have already shipped with OS versions 2.3 to 2.3.3.
Your situation is that you've probably hit the end of the file in one read and the stream is automatically closed. I think that is a bug introduced in Android 2.3 and above.
glassonion's post will work, but that workaround will perform very slowly on long streams of data.
Since mobile applications may lose internet connectivity at any time, the InputStream you're reading from may just simply be blocked and waiting for more data.
A more proper approach may be to open a socket on a new thread, read the data and wait with a timeout to hedge against any slowness in your connection.
The following article explains handling stalled connections quite well. Reading the summary should be enough to convince you.
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.
回答2:
workaround is below.
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();
来源:https://stackoverflow.com/questions/4841925/java-io-ioexception-bufferedinputstream-is-closed-in-android-2-3