0

ZipInputStream クラスを使用して抽出したい複数のファイルをそれぞれ含む複数の zip ファイルがあります。その中にはいくつかの画像があります。BufferedOutputStream を使用してこれらの画像を抽出しようとすると、部分的に解凍され、画像が不完全になります。

private void extractArchives() {

    ZipInputStream zis;

    File archiveDir = new File(
             Environment.getExternalStorageDirectory().getAbsolutePath() +
     "/archives/");

    File[] files = archiveDir.listFiles();

    for (int i = 0; i < files.length; ++i)
    {
        File file = files[i];

        try
        {
            zis = new ZipInputStream(new FileInputStream(file));
            ZipEntry ze;

            while ((ze = zis.getNextEntry()) != null)
            {
                BufferedOutputStream bos;
                byte[] buffer = new byte[102400];
                int count;

                while ((count = zis.read(buffer)) != -1)
                {
                    String fileName = ze.getName();

                    if (fileName.endsWith(".jpg"))
                    {
                        path += File.separator + fileName;
                        bos = new BufferedOutputStream(new FileOutputStream(path));
                        bos.write(buffer, 0, count);
                        bos.close();
                    }
                }
            }

            zis.close();

        }

        catch(FileNotFoundException e) { continue; }

        //If the file is not a zip file or is a directory
        catch (IOException e) { continue; }

    }
}

上記のコードに何か問題がありますか?BufferedOutputStream を使用すると、この問題が発生しますか? アイデアをいただければ幸いです。ありがとう。

4

2 に答える 2

0

zip エントリを反復処理するループに注目すると、問題は、zip エントリから最大 102400 バイトを読み取り、それを新しいファイルに書き込んでいたことです。同じ画像ファイルが新しいファイルに書き込まれた場合、次の最大 102400 バイト。パス名が古いファイルと同じ場合、古いファイルが上書きされます。しかし、ローカル変数「パス」に常に追加していたため、データがどこにあるのかわかりません。

FileOutputStream の開始部分を内側のループから取り出し、現在の ZipEntry からバイトを読み取れなくなるまで、同じ OutputStream への書き込みを続けます。その後、次の ZipEntry と次の OutputStream に移動します。

これは、Java のストリーム間で読み取りとコピーを行うための標準的なパターンであるため、 の定義がなくてもコードを修正できます。filesただしpathzis実際のコンパイル コードの例を投稿して、他の人もこの恩恵を受けることができると助かります。

プロダクション コードで必要なもう 1 つの改善点はbos.close()、入力からの読み取り中に例外が発生した場合に出力ファイルも閉じられるように、try/finally ブロックでラップすることです。

        while ((ze = zis.getNextEntry()) != null) {
            String fileName = ze.getName();

            if (fileName.endsWith(".jpg")) {
                String filepath = path + File.separator + fileName;
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filepath));
                byte[] buffer = new byte[102400];
                int count;
                while ((count = zis.read(buffer)) != -1) {
                    bos.write(buffer, 0, count);
                }
                bos.close();
            }
        }
于 2014-01-20T16:06:15.033 に答える