0

Socket InputStream から取得したバイト配列を使用して複数のファイルを作成するアプリがあります。1 つのファイルを保存するだけでファイルは完全に保存されますが、1 つのファイルを保存してからファイル ストリームを再インスタンス化して別のファイルを保存すると、最初のファイルは破損し、2 番目のファイルは完全に保存されます。2 つのファイルをテキスト エディターで開いたところ、(約...) 最初のファイルの最初の 1/5 は空白ですが、2 番目のファイルはいっぱいで、両方とも同じサイズのプロパティ (9,128,731 バイト) を持っているようです。次の例はシナリオの複製ですが、破損の結果は同じです。

FileOutputStream outStream;
outStream = new FileOutputStream("/mnt/sdcard/testmp3.mp3");
File file = new File("/mnt/sdcard/test.mp3");
FileInputStream inStream = new FileInputStream(file);
byte[] buffer = new byte[9128731];
inStream.read(buffer);
outStream.write(buffer, 0, buffer.length);
inStream.close();
outStream.flush();
outStream.close();
outStream = null;
outStream = new FileOutputStream("/mnt/sdcard/testmp32.mp3");
outStream.write(buffer, 0, buffer.length);
inStream.close();
outStream.flush();
outStream.close();
outStream = null;

この EXACT コードを通常の Java アプリケーションで試したところ、両方のファイルが問題なく保存されました。Androidがこれを行っている理由を誰かが知っていますか?

どんな助けでも大歓迎です

4

4 に答える 4

5

jtahlbornが述べたように、それInputStream.read(byte[])が常に必要な数のバイトを読み取るとは限りません。また、このような大きなバイト配列を使用して一度に書き出すことは避けてください。少なくともバッファリングなしでは、何かがオーバーフローする可能性があります。次のようにファイルをコピーすることで、これらの懸念に対処し、メモリを節約できます。

File inFile = new File("/mnt/sdcard/test.mp3");
File outFile = new File("/mnt/sdcard/testmp3.mp3");
FileInputStream inStream = new FileInputStream(inFile);
FileOutputStream outStream = new FileOutputStream(outFile);
byte[] buffer = new byte[65536];
int len;
while ((len = inStream.read(buffer)) != -1) {
    outStream.write(buffer, 0, len);
}
inStream.close();
outStream.close();
于 2011-03-27T08:03:39.557 に答える
1

デバッグを開始する可能性のあるいくつかの潜在的な問題があります。

  1. 入力ストリームを閉じる前に、最初の出力ストリームに書き込みます。これは少し奇妙です。

  2. テキストエディタを使用して、2つのバイナリファイル間の類似性/相違性を正確に測定することはできません。あなたは16進エディタ(またはより良い、Audacity)でファイルを見る必要があります

  3. BufferedOutputStreamAndroidドキュメントで提案されているよう に使用します:http: out = new BufferedOutputStream(new FileOutputStream(file)); //developer.android.com/reference/java/io/FileOutputStream.html

  4. デバッグ手法として、buffer最初の書き込み後の内容を出力します。また、をinStream.read()返しますint。さらにこれを比較しbuffer.lengthて、同じであることを確認します。とにかく、あなたが本当に正当な理由がない限り、私はwrite(buffer)代わりにただ電話するでしょう。write(buffer, 0, buffer.length)

-tjw

于 2011-03-23T03:12:59.953 に答える
0

呼び出しが必要な数のバイトを読み取ると想定していread()ます。それは正しくありません。そのメソッドは、1 から buffer.length バイトまで自由に読み取ることができます。そのため、実際に読み取られたバイト数を判断するには、常に戻り値を使用する必要があります。Javaストリームから正しく読み取る方法(つまり、バッファを完全に埋める方法)を示すストリームチュートリアルがたくさんあります。

于 2011-03-23T03:18:15.290 に答える
0

誰かが同じ問題を抱えていて、それをどのように修正するのか疑問に思っている場合、問題の原因は私の SD カードであることがわかりました。私は 32 GB のキングストン SD カードを購入しましたが、ちょうど昨日、代わりに内部ストレージを使用して同じコードを再度実行してみることにしました。すべてが完全に機能しました。付属の 2GB SD カードも試してみましたが、完璧に動作しました。私のコードがうまく機能することを知ってうれしく思いますが、欠陥のあるメモリ カードに 50 ドルを費やしたことに少し不満を感じていました。皆様のご意見をお寄せいただきありがとうございます。

于 2011-03-27T07:50:25.080 に答える