为什么在这种情况下我必须以某种方式关闭 ZipOutputStream?
Why do I have to close the ZipOutputStream in a certain way in this situation?
我有两个例子:
示例 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 示例没有像我希望的那样工作。
我的意思是文件内容不是空的,而是'
好像 zip 文件已损坏。
我想请你告诉我为什么第一个例子不起作用。
ZipOutputStream
has to do several operations at the end of the stream 完成 zip 文件,因此有必要正确关闭它。 (一般来说,几乎每个流 都应该 正确关闭,这是一种很好的做法。)
嗯,看起来 try-with-resources 自动关闭顺序很重要,在展开东西时必须先关闭 ZipOutputStream。在此上下文中,自动关闭的顺序与它们的创建顺序相反。
如果您重新排序第二个示例,使 ZipOutputStream 位于 FileOutputStream 之后,会发生什么情况? (虽然如果你问我,将 ZipOutputStream 放在它自己的 try-catch 块中是更清晰的代码。我们将相关和不相关的流分开,并以易于阅读的方式处理自动关闭。)
更新
FWIW,这是我过去在将 zip 流式传输到缓冲输出流时使用的那种习惯用法:
try (final ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(
new FileOutputStream(zipFile.toString())))) { ... }
我有两个例子:
示例 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 示例没有像我希望的那样工作。 我的意思是文件内容不是空的,而是' 好像 zip 文件已损坏。
我想请你告诉我为什么第一个例子不起作用。
ZipOutputStream
has to do several operations at the end of the stream 完成 zip 文件,因此有必要正确关闭它。 (一般来说,几乎每个流 都应该 正确关闭,这是一种很好的做法。)
嗯,看起来 try-with-resources 自动关闭顺序很重要,在展开东西时必须先关闭 ZipOutputStream。在此上下文中,自动关闭的顺序与它们的创建顺序相反。
如果您重新排序第二个示例,使 ZipOutputStream 位于 FileOutputStream 之后,会发生什么情况? (虽然如果你问我,将 ZipOutputStream 放在它自己的 try-catch 块中是更清晰的代码。我们将相关和不相关的流分开,并以易于阅读的方式处理自动关闭。)
更新
FWIW,这是我过去在将 zip 流式传输到缓冲输出流时使用的那种习惯用法:
try (final ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(
new FileOutputStream(zipFile.toString())))) { ... }