使用FileUtils.copyFile复制zip后解压报java.util.zip.ZipException异常
Java解压复制后的ZIP文件报错invalid distances set解决方案
异常信息
java.util.zip.ZipException: invalid distances set at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:165) at java.base/java.util.zip.ZipInputStream.read(ZipInputStream.java:195) at java.base/java.io.FilterInputStream.read(FilterInputStream.java:107)
触发场景与前置验证
- 文件先通过
org.apache.commons.io.FileUtils.copyFile(File srcFile, File destFile)或Google Guava文件复制API完成复制,对复制后的目标文件执行解压操作时报错 - 直接解压原始ZIP文件无异常,复制后的文件大小与原文件完全一致,可通过7Zip正常打开,内容无缺失
- 故障复现使用的是大体积AdoptOpenJDK ZIP包,已排除解压逻辑本身的代码错误
根因说明
该问题是JDK内置java.util.zip工具包的兼容性限制导致:
AdoptOpenJDK的官方ZIP包多使用Deflate64或ZIP64扩展格式打包,JDK内置的zip解压实现默认不支持该类扩展压缩格式,而7Zip等第三方解压工具做了兼容,所以可以正常打开。文件复制操作本身不会修改包内压缩数据,只是触发了JDK解压逻辑对这类非标准压缩格式的校验报错。
修复方案
方案1:替换为兼容度更高的解压库
使用Apache Commons Compress库替代JDK内置的zip处理工具,该库原生支持Deflate64、ZIP64等扩展压缩格式,适配绝大多数场景的ZIP包解压需求。
方案2:调整JDK内置解压参数
如果必须使用JDK内置工具实现,构造ZipInputStream时显式传入开启nowrap模式的Inflater实例,适配扩展压缩格式:
// 解压核心代码调整示例 Inflater inflater = new Inflater(true); try (ZipInputStream zis = new ZipInputStream(new FileInputStream(destZipFile), StandardCharsets.UTF_8, inflater)) { // 原有解压逻辑保持不变 }
方案3:补充复制完整性校验
在文件复制完成后、执行解压前增加文件哈希校验,排除低概率的文件系统缓存未刷盘导致的文件不完整问题:
// 使用Apache Commons IO工具类做MD5校验 String srcFileMd5 = FileUtils.checksum(srcFile, new MD5Checksum()).toString(); String destFileMd5 = FileUtils.checksum(destFile, new MD5Checksum()).toString(); if (!srcFileMd5.equals(destFileMd5)) { throw new IOException("文件复制过程损坏,请重试"); }
内容的提问来源于stack exchange,提问作者micmei
相关产品推荐
相关产品推荐

