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

私もこれに気付きました。できることの 1 つは、ループの最後で 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 公式サイトのバグベースに投稿して、Google にこの問題の修正を依頼してください。残念ながら、OS バージョン 2.3 から 2.3.3 がすでに出荷されているデバイスが多数あります。

あなたの状況は、おそらく 1 回の読み取りでファイルの終わりに到達し、ストリームが自動的に閉じられたということです。これは Android 2.3 以降で導入されたバグだと思います。

グラソニオンの投稿は機能しますが、その回避策は長いデータ ストリームでは非常に遅くなります。

モバイル アプリケーションはいつでもインターネット接続を失う可能性があるため、読み取り元の InputStream は単純にブロックされ、次のデータを待機している可能性があります。

より適切なアプローチは、新しいスレッドでソケットを開き、データを読み取り、タイムアウトで待機して、接続の速度低下を回避することです。

次の記事では、ストールした接続の処理について詳しく説明しています。要約を読むだけで十分に納得できます。

すべての優れたネットワーク アプリケーションには、タイムアウトの検出と処理が含まれます。クライアントを作成していてわがままなサーバーを検出する必要がある場合でも、サーバーを作成していて接続の停止を防ぐ必要がある場合でも、タイムアウト処理はエラー処理の重要な部分です。

于 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 に答える