Java原生解压ZIP需用java.util.zip包,推荐ZipInputStream逐条处理并校验路径防穿越,或ZipFile批量读取;务必标准化路径、检查越界、确保中文名支持及资源自动释放。

Java 原生就能解压 ZIP 文件,用 java.util.zip 包里的 ZipInputStream 或 ZipFile 类即可,无需额外依赖。关键是要安全、完整地还原目录结构和文件内容,尤其注意路径校验和中文名支持。
用 ZipInputStream 逐条解压(推荐,控制力强)
适合需要动态处理每个条目(如过滤、重命名、校验)的场景。核心逻辑是:打开 ZIP 流 → 遍历每个 ZipEntry → 校验路径合法性 → 创建目标文件或目录 → 写入数据。
- 先调用
zipIn.getNextEntry()获取条目,循环直到返回null - 对每个条目的名字(
entry.getName())做路径标准化:Paths.get(name).normalize(),再检查是否以目标根目录为前缀,防止../路径穿越 - 若条目名以
/结尾,说明是目录,用file.mkdirs()创建;否则是文件,先确保父目录存在,再用Files.write()或FileOutputStream写入内容 - 每次读完一个条目后,记得调用
zipIn.closeEntry()
用 ZipFile 批量读取(更简洁,适合只提取)
ZipFile 是基于随机访问的类,适合一次性列出所有条目并按需提取,代码更直观,资源管理也更明确。
- 用
new ZipFile(file)打开压缩包,配合 try-with-resources 自动关闭 - 调用
zipFile.entries()得到枚举,遍历每个ZipEntry - 提取单个文件时,用
zipFile.getInputStream(entry)获取输入流,再写入本地文件 - 同样要对
entry.getName()做路径规范化和越界检查,不能直接拼接
必须处理的三个细节问题
忽略这些容易出错或被攻击:
立即学习“Java免费学习笔记(深入)”;
-
路径安全:绝不能直接用
entry.getName()构造File对象。必须normalize()并确认结果路径在目标根目录内(例如targetDir.toPath().resolve(normalizedPath).startsWith(targetDir.toPath())) -
中文文件名:Java 7+ 默认生成的 ZIP 若用 UTF-8 编码保存中文名,
ZipInputStream和ZipFile通常能自动识别;但如果遇到乱码,可尝试用第三方库(如 Apache Commons Compress)显式指定编码,原生方案一般无需额外设置 -
资源释放:务必用 try-with-resources 包裹
ZipInputStream、ZipFile、FileInputStream和FileOutputStream,避免句柄泄漏


















