【问题标题】:Why do I have to close the ZipOutputStream in a certain way in this situation?为什么在这种情况下我必须以某种方式关闭 ZipOutputStream?
【发布时间】:2015-02-20 19:06:31
【问题描述】:

我有两个例子:

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

second 示例无法正常工作。 我的意思是文件内容不是空的,但它' s 好像 zip 文件已损坏。

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

【问题讨论】:

    标签: java file outputstream zipoutputstream


    【解决方案1】:

    ZipOutputStreamhas to do several operations at the end of the stream 完成压缩文件,所以必须正确关闭它。 (一般来说,几乎每个流都应该正确关闭,这也是一种好的做法。)

    【讨论】:

    • 某种未定义的行为。我的猜测是 FileOutputStream 是先关闭的,这意味着刷新,但是有数据需要先被嵌套流消费。
    • @chikamatsu 我认为你在该图片的右侧有错误的文件 - 它似乎是一个文本文件,其中的值,所以它不是一个压缩文件,你没有比较正确的文件。
    • 哎呀,你是对的,我弄错了,这是正确的截图:(再次,错误的在左边)puu.sh/g5pj3.png
    【解决方案2】:

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

    如果您对第二个示例重新排序以使 ZipOutputStream 在 FileOutputStream 之后会发生什么? (尽管如果你问我,将 ZipOutputStream 放在它自己的 try-catch 块中是更清晰的代码。我们将相关和不相关的流分开,并以易于阅读的方式处理自动关闭。)

    更新

    FWIW,这是我过去在将 zip 流式传输到缓冲输出流时使用的那种习惯用法:

    try (final ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(
                        new FileOutputStream(zipFile.toString())))) { ... }
    

    【讨论】:

    • 它发生了完全相同的事情(它没有工作,但可能文件内容不一样)。我不明白的是 ByteArrayOutputStream 和 ZipOutputStream 的行为。
    • 那么不确定。我刚刚意识到,在您决定写出 ByteArrayOutputStream 之前,并没有真正使用 FileOutputStream。因此,在您完成 zip(包括关闭它)之后,它确实应该在自己的 try 块中。
    猜你喜欢
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多