简体   繁体   English

使用 ByteArrayOutputStream 创建的 Java Zip 文件小于使用 FileOutputStream

[英]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.

相关问题 Java FileOutputStream创建的文件未解锁 - Java FileOutputStream Created file Not unlocking Java:FileOutputStream和ByteArrayOutputStream之间的字符串比较 - Java: String Comparison between FileOutputStream and ByteArrayOutputStream FileOutputStream与ByteArrayOutputStream - FileOutputStream vs ByteArrayOutputStream Java ByteArrayOutputStream 上的堆 OutOfMemory 用于 deflater zip 字节 - Java Heap OutOfMemory on ByteArrayOutputStream for deflater zip bytes Java File.createNewFile() 比 FileOutputStream 慢得多 - Java File.createNewFile() much slower than just FileOutputStream 保留文件的Java FileOutputStream? - A Java FileOutputStream that keeps the File? 将ByteArrayOutputStream写入FileOutputStream vs将ByteArray写入FileOutputStream? - Write ByteArrayOutputStream to FileOutputStream vs Write ByteArray to FileOutputStream? 通过ByteArrayOutputStream打印创建的iText pdf文件 - Printing created iText pdf file by ByteArrayOutputStream 在DropHandler中使用Vaadin StreamVariable时,使用ByteArrayOutputStream.writeTo(FileOutputStream)创建文件失败? - Creating a file using ByteArrayOutputStream.writeTo(FileOutputStream) fails when using Vaadin StreamVariable in DropHandler? PHP和Java FileOutputStream编写的文件 - PHP and a file written by Java FileOutputStream
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM