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) {}

第二例子不像我想要的那样工作。我的意思是文件内容不为空,但好像 zip 文件已损坏。

我想让你告诉我为什么第一个例子不起作用。

4

2 回答 2

3

ZipOutputStream 必须在流的末尾执行几个操作才能完成 zip 文件,因此必须正确关闭它。(一般来说,几乎每个流都应该正确关闭,这也是一种很好的做法。)

于 2015-02-20T19:11:50.813 回答
0

好吧,看起来 try-with-resources 自动关闭顺序很重要,并且 ZipOutputStream 在展开时必须先关闭。在这种情况下,自动关闭的发生顺序与它们的创建顺序相反。

如果您重新排序第二个示例以使 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 回答