2

私は2つの例を持っています:

例 1:

try (ByteArrayOutputStream baous = new ByteArrayOutputStream();     
    FileOutputStream fouscrx = new FileOutputStream(new File(output, "example"))) {
        try (ZipOutputStream zous = new ZipOutputStream(baous)) {
            for (File file: files) {
                try (FileInputStream fis = new FileInputStream(file)) {
                    ZipEntry zipEntry = new ZipEntry(file.getPath().substring(output.getPath().length() + 1));
                    zous.putNextEntry(zipEntry);
                    byte[] bytes = new byte[2048];
                    int length;
                    while ((length = fis.read(bytes)) >= 0) {
                        zous.write(bytes, 0, length);
                    }
                    zous.closeEntry();
                }
            }
        }
        baous.writeTo(fouscrx);
    } catch (FileNotFoundException ex) {} catch (IOException ex) {}

例 2:

try (ByteArrayOutputStream baous = new ByteArrayOutputStream();
          ZipOutputStream zous = new ZipOutputStream(baous);
       FileOutputStream fouscrx = new FileOutputStream(new File(output, "example"))) {
            for (File file: files) {
                try (FileInputStream fis = new FileInputStream(file)) {
                    ZipEntry zipEntry = new ZipEntry(file.getPath().substring(output.getPath().length() + 1));
                    zous.putNextEntry(zipEntry);
                    byte[] bytes = new byte[2048];
                    int length;
                    while ((length = fis.read(bytes)) >= 0) {
                        zous.write(bytes, 0, length);
                    }
                    zous.closeEntry();
                }
            }
            baous.writeTo(fouscrx);
        } catch (FileNotFoundException ex) {} catch (IOException ex) {}

2 番目のは、私が望んでいるようには機能しません。つまり、ファイルの内容は空ではありませんが、zip ファイルが破損しているかのようです。

最初の例がうまくいかない理由を教えてください。

4

2 に答える 2

3

ZipOutputStream ストリームの最後でいくつかの操作を実行して zip ファイルを完成させる必要があるため、適切に閉じる必要があります。(一般的に言えば、ほとんどすべてのストリームは適切に閉じる必要があります。これは良い習慣です。)

于 2015-02-20T19:11:50.813 に答える
0

まあ、try-with-resources の自動終了順序が重要なようです。巻き戻しを行うときは、最初に ZipOutputStream を閉じる必要があります。自動クローズは、このコンテキストでの作成とは逆の順序で発生します。

2 番目の例を並べ替えて、ZipOutputStream が FileOutputStream の後にあるとどうなりますか? (ただし、ZipOutputStream を独自の try-catch ブロックに配置した方がわかりやすいコードです。関連するストリームと関連しないストリームを分離し、読みやすい方法で自動クローズを処理します。)

アップデート

FWIW、これは、バッファリングされた出力ストリームに zip をストリーミングするときに、過去に使用した一種のイディオムです。

try (final ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(
                    new FileOutputStream(zipFile.toString())))) { ... }
于 2015-02-20T19:34:31.217 に答える