2

大きな pdf ファイル (3.7 mb) を raw フォルダーから外部キャッシュ ディレクトリにコピーしようとしています。

次のコードを使用しています。

int i = 0;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) 
        {           
            InputStream input = getResources().openRawResource(pdfs[i]);
            File file = new File(Environment.getExternalStorageDirectory(), "/Android/data/eu.app/cache/" + pdfNames[i]);

            if(!file.exists())
            {
                try
                {
                    new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/eu.app/cache").mkdirs();
                    FileOutputStream fos = new FileOutputStream(file.toURI().getPath(), false);

                    OutputStream os = new BufferedOutputStream(fos);



                    byte[] buffer = new byte[1024];
                    int byteRead = 0;


                    while ((byteRead = input.read(buffer)) != -1) {

                            os.write(buffer, 0, byteRead);
                    }

                    fos.close();

                }
                catch(Exception ex)
                {
                    Log.d("storage", ex.getMessage()); 

                }
            }               
        }
        else
        {

        }

エラーは発生しませんが、出力ファイルは元のファイルよりも数バイト小さく、開くことができません。これを修正するにはどうすればよいですか?

4

2 に答える 2

2

主な問題は、OSを閉じる必要があるときにfosを閉じることだと思います。また、close 操作を finally ブロックに入れる必要があります。

更新 (現在はフル キーボードで ;)):バッファリングされたストリームがフラッシュされる前に、ファイル ストリーム (fos) を閉じます。すべきことは、バッファリングされたストリーム (os) を閉じることです。これにより、バッファがフラッシュされ、不足しているバイトが書き込まれ、基になるファイル ストリームが自動的に閉じられます。それを修正するには、に変更fos.close()os.close()ます。

さらに、ストリームを常に閉じるようにするには、close 操作を finally ブロックに配置する必要があります。典型的なパターンは次のとおりです。

BufferedInputStream in = null;
try {
    in = new BufferedInputStream(anInputStream);

    BufferedOutputStream out = null;
    try {
        out = new BufferedOutputStream(new FileOutputStream(aFile));
        // Read and write what you should write
    }
    finally {
        if (out != null) out.close();
    }
} finally {
    if (in != null) in.close();
}

入力ストリームは簡単に追加できますが、すべてのストリームが閉じていることを確認してください。これは、finally ブロックをネストするか、finally ブロック内に try-catch ブロックをネストすることで処理できます。

このメソッドから IOException をスローして外部で処理するか (多くの場合推奨)、上記のコードを新しい try-catch ステートメントでラップしてそこで処理します。ただし、メソッド内でそれを処理すると、UI とロジックが混在し、多くの場合、UI とロジックを分離するコードがより明確になります。

最後の注意: 1024 はかなり小さいです。さまざまな値で遊んでください。一方、バッファリングされたストリームはバッファリングを処理します。

于 2012-09-10T19:46:56.927 に答える
0

あるストリームから別のストリームへの読み取りにこの関数を数年間使用してきましたが、結果のファイルに問題はありませんでした。ソース ファイルとターゲット ファイルをそのまま開き、それぞれのストリームをこの関数に渡します。

public static void streamToStream(InputStream is, OutputStream os) {

    int count = 0;
    try {
        while(count != -1) {
            byte[] bytes = new byte[2048];
            count = is.read(bytes);
            if(count == -1) {
                continue;
            }

            os.write(bytes, 0, count);
            bytes = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
于 2012-09-10T19:32:51.437 に答える