Java - try-with-resources 中的 ZipOutputStream

Java - ZipOutputStream within try-with-resources

我有这个 Java 代码可以创建并保存一个包含文本文件的 zip 文件:

public static void main(String[] args) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ZipOutputStream zos = new ZipOutputStream(baos)) {
        String s = "Hello, world!";
        ZipEntry entry = new ZipEntry("text_file.txt");
        zos.putNextEntry(entry);
        zos.write(s.getBytes());
        zos.closeEntry();

        try (OutputStream os = new FileOutputStream("zip_file.zip")) {
            baos.writeTo(os);
            System.out.println("ZIP file created successfully");
        }
    } catch (IOException e) {
        System.out.println("Error: " + e);
    }
}

这段代码的问题是它创建了一个损坏的 zip 文件,所以我无法提取甚至打开其中的内容。

最终我发现,如果我通过在 zos.closeEntry() 之后放置 zos.close() 来手动关闭 ZipOutputStream,则可以成功创建 zip 文件而不会损坏。老实说,这对我来说没有任何意义,因为我已经在 try-with-resource 语句中声明了 ZipOutputStream,所以我希望它会自动关闭。

看来try-with-resource语句实际上并没有关闭流。我做错了什么吗?

如有任何帮助,我们将不胜感激。

OS: Windows 10

注意:我使用 ByteArrayOutputStream 因为在实际情况下我必须在内存中创建 zip 文件,因为我在磁盘上没有可以依赖的文件夹。

try-with-resources确实关闭了ZipOutputStream。只是在您将其内容复制到 FileOutputStream 后它会关闭 zip 流。您期望文件关闭后发生的工作如何影响文件的内容?

我建议将 ByteArrayOutputStream 替换为 FileOutputStream。你有什么需要缓冲的?

try (OutputStream os = new FileOutputStream("zip_file.zip");
     ZipOutputStream zos = new ZipOutputStream(os)) {
  String s = "Hello, world!";
  ZipEntry entry = new ZipEntry("text_file.txt");
  zos.putNextEntry(entry);
  zos.write(s.getBytes());
  zos.closeEntry();
}
System.out.println("ZIP file created successfully");

原来我放错了 ByteArrayOutputStream 对象:我不应该通过将它放在 try-with-resource 语句中来关闭它,因为正如 here 所解释的那样,ByteArrayOutputStream 完全基于内存,因此分配的内存将由垃圾收集器自动释放。

以下代码产生所需的结果:

public static void main(String[] args) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    try (ZipOutputStream zos = new ZipOutputStream(baos)) {
        String s = "Hello, world!";
        ZipEntry entry = new ZipEntry("text_file.txt");
        zos.putNextEntry(entry);
        zos.write(s.getBytes());
        zos.closeEntry();
    } catch (IOException e) {
        System.out.println("Error: " + e);
    }

    try (OutputStream os = new FileOutputStream("zip_file.zip")) {
        baos.writeTo(os);
        System.out.println("ZIP file created successfully");
    } catch (IOException e) {
        System.out.println("Error: " + e);
    }
}