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);
}
}
我有这个 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);
}
}