You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用java.util.zip生成Zip文件时尺寸未正确写入,如何解决?

解决java.util.zip写入Zip后ZipInputStream无法获取entry尺寸的问题

这个问题我之前也碰到过,核心原因是ZipOutputStream的流式写入特性:当你直接写入文件/流内容而没有提前设置ZipEntry的尺寸时,它只会把尺寸信息写入zip文件的中央目录,而不会写到每个entry的局部文件头里。而ZipInputStream是从局部文件头读取getSize()和getCompressedSize()的值的,自然就返回-1;但ZipFile是直接读取中央目录的,所以能拿到正确值。

下面给你两种可行的解决方案:

1. 提前获取原始文件尺寸(适用于本地文件场景)

如果你的数据源是本地文件,直接通过File.length()获取原始大小,然后设置到ZipEntry中。这样ZipOutputStream会把尺寸信息写入局部文件头,ZipInputStream就能正确读取了:

try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("output.zip"))) {
    File targetFile = new File("your-file.txt");
    ZipEntry entry = new ZipEntry(targetFile.getName());
    
    // 关键:提前设置原始文件大小
    entry.setSize(targetFile.length());
    
    zos.putNextEntry(entry);
    Files.copy(targetFile.toPath(), zos);
    zos.closeEntry();
}

2. 缓存动态流数据获取尺寸(适用于网络流/未知大小的流)

如果你的数据源是动态流(比如网络请求返回的流,无法提前知道大小),可以先把流数据缓存到内存或临时文件,计算出原始大小和压缩后的大小,再写入ZipOutputStream:

// 1. 先读取动态流到内存,获取原始大小
ByteArrayOutputStream rawDataBaos = new ByteArrayOutputStream();
try (InputStream inputStream = yourDynamicInputStream()) {
    byte[] buffer = new byte[4096];
    int bytesRead;
    while ((bytesRead = inputStream.read(buffer)) != -1) {
        rawDataBaos.write(buffer, 0, bytesRead);
    }
}
byte[] rawData = rawDataBaos.toByteArray();

// 2. 预压缩数据,获取压缩后的大小
ByteArrayOutputStream compressedBaos = new ByteArrayOutputStream();
try (DeflaterOutputStream deflaterStream = new DeflaterOutputStream(compressedBaos)) {
    deflaterStream.write(rawData);
}
byte[] compressedData = compressedBaos.toByteArray();

// 3. 写入ZipOutputStream,设置两个尺寸
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("output.zip"))) {
    ZipEntry entry = new ZipEntry("dynamic-content.txt");
    entry.setSize(rawData.length);
    entry.setCompressedSize(compressedData.length);
    
    zos.putNextEntry(entry);
    zos.write(compressedData);
    zos.closeEntry();
}

补充说明

  • 如果你不需要getCompressedSize(),只需要getSize(),那么只设置entry.setSize()就足够了,压缩后的大小会自动写入中央目录,但局部文件头还是没有,所以ZipInputStream拿不到,但至少原始大小是对的。
  • 不要忘记关闭ZipEntry和流,确保资源正确释放。

内容的提问来源于stack exchange,提问作者Neph

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:15:57