[英]Java Zip File Created With ByteArrayOutputStream is smaller than with FileOutputStream
The Zip file output from using ByteArrayOuputStream is smaller than that with FileOutputStream.使用 ByteArrayOuputStream 输出的 Zip 文件小于使用 FileOutputStream 输出的 Zip 文件。
In Java I am creating a Zip file.在 Java 中,我正在创建一个 Zip 文件。 Which opens successfully when I use FileOutputStream.
当我使用 FileOutputStream 时成功打开。
When switching the FileOutputStream to a ByteArrayOutputStream I get a slightly smaller file, about 221 bytes.将 FileOutputStream 切换到 ByteArrayOutputStream 时,我得到一个稍小的文件,大约 221 字节。 And this file won't open, but has the same contents as the other but missing 221 bytes.
这个文件不会打开,但与另一个文件具有相同的内容,但缺少 221 个字节。
The logic I use to construct the Zip file is the same in both cases.我用来构建 Zip 文件的逻辑在这两种情况下都是相同的。 Therefore I will share the essential logic without the zip creation (let me know if you need this).
因此,我将在不创建 zip 的情况下分享基本逻辑(如果您需要,请告诉我)。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
zipOS = new ZipOutputStream(baos);
Then I create the Zip file, and then ...然后我创建 Zip 文件,然后...
zipOS.flush();
baos.flush();
baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip"));
zipOS.close();
baos.close();
I'm using the baos.writeTo() to bypass this to prove it's not the HTTP response but the ByteArrayOutputStream element thats an issue.我正在使用 baos.writeTo() 绕过它以证明它不是 HTTP 响应,而是 ByteArrayOutputStream 元素,这是一个问题。
When using baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip"));
当使用
baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip"));
I get a smaller file that doesn't open as a Zip.我得到一个较小的文件,它不能以 Zip 格式打开。
This logic is in a java controller so that a link clicked on web page will down load the zip file without touching any file systems excepted the users.此逻辑位于 java 控制器中,因此单击网页上的链接将下载 zip 文件,而不会触及除用户之外的任何文件系统。
Here is the code using FileOutputStream which works...这是使用 FileOutputStream 的代码,它可以工作...
FileOutputStream baos = new FileOutputStream("TEST_AS_FILE.zip");
zipOS = new ZipOutputStream(baos);
Aside from the the second code snippet isn't relevant as I would need to send the file created on the web server.除了第二个代码片段不相关,因为我需要发送在 Web 服务器上创建的文件。 But the point is, that Fileoutput stream with the same logic and ByteArrayOutputStream has a difference.
但重点是,具有相同逻辑的 Fileoutput 流和 ByteArrayOutputStream 是有区别的。
The following statement is wrong:以下说法是错误的:
baos.writeTo(new FileOutputStream("TEST_AS_BYTESTREAM_1.zip"));
The javadoc of writeTo(OutputStream out)
does not say anything about closing the OutputStream
, which means it doesn't, so the last of the data is still sitting buffered in the un-closed, un-flushed FileOutputStream
. writeTo(OutputStream out)
的 javadoc 没有说明关闭OutputStream
任何内容,这意味着它没有,所以最后的数据仍然缓冲在未关闭、未刷新的FileOutputStream
。
The correct way is:正确的方法是:
try (OutputStream out = new FileOutputStream("TEST_AS_BYTESTREAM_1.zip")) {
baos.writeTo(out);
}
Also, a ByteArrayOutputStream
does not need to be closed or flushed.此外,不需要关闭或刷新
ByteArrayOutputStream
。 As the javadoc of close()
says it:正如
close()
的 javadoc 所说:
Closing a
ByteArrayOutputStream
has no effect.关闭
ByteArrayOutputStream
没有任何效果。
You will however need to call finish()
on an ZipOutputStream
to complete the content.但是,您需要在
ZipOutputStream
上调用finish()
以完成内容。 Since closing the zip stream automatically finishes it for you, the correct way to do this is:由于关闭 zip 流会自动为您完成,因此执行此操作的正确方法是:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zipOS = new ZipOutputStream(baos)) {
// create the Zip file content here
}
try (OutputStream out = new FileOutputStream("TEST_AS_BYTESTREAM_1.zip")) {
baos.writeTo(out);
}
When writing directly to a file:直接写入文件时:
try (ZipOutputStream zipOS = new ZipOutputStream(new FileOutputStream("TEST_AS_FILE.zip"))) {
// create the Zip file content here
}
Consider adding a BufferedOutputStream
for better performance.考虑添加
BufferedOutputStream
以获得更好的性能。
The final answer is as follows.最终答案如下。 Many thanks to the answer previously given.
非常感谢之前给出的答案。
Basically I needed to use the .finish() method of the ZipOuputStream.基本上我需要使用 ZipOuputStream 的 .finish() 方法。 Everything else remained the same.
其他一切都保持不变。
Pre zip creation code same as before Pre zip 创建代码与之前相同
ByteArrayOutputStream baos = new ByteArrayOutputStream();
zipOS = new ZipOutputStream(baos);
Post zip creation...邮编创建...
zipOS.flush();
zipOS.finish();
baos.flush();
documentBody = baos.toByteArray();
zipOS.close();
baos.close();
Then my HTTP response is然后我的 HTTP 响应是
HttpHeaders headers = new HttpHeaders();
headers.setContentType(new MediaType("application", "zip"));
headers.setContentLength(documentBody.length);
headers.add("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
ByteArrayResource resource = new ByteArrayResource(documentBody);
return ResponseEntity.ok()
.headers(headers)
.body(resource);
This way I avoid the creation of a file which is nice.这样我就避免了创建一个很好的文件。
Many thanks for the assistance.非常感谢您的帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.