Java中ZipInputStream解压ZIP需逐个读取ZipEntry、手动创建目录结构、校验路径防遍历,支持UTF-8编码但不支持随机访问。

Java 中使用 ZipInputStream 解压 ZIP 文件,核心是逐个读取 ZIP 中的条目(ZipEntry),再按需提取内容。它适合流式处理、内存受限或边解压边处理的场景,但不支持随机访问或直接解压到目录——需要手动创建文件和目录结构。
基本解压流程(含文件创建)
解压 ZIP 需要:打开 ZIP 输入流 → 遍历每个 ZipEntry → 判断是目录还是文件 → 创建对应路径 → 写入内容。
- 用
new ZipInputStream(new FileInputStream("xxx.zip"))包装原始输入流 - 调用
getNextEntry()获取下一个条目;返回null表示结束 - 对每个
ZipEntry,检查isDirectory();是目录则用File.mkdirs()创建;是文件则先确保父目录存在,再用Files.newOutputStream()或FileOutputStream写入 - 用普通字节读写循环(如
read(byte[]))从ZipInputStream复制数据到目标输出流 - 每次处理完一个条目后,必须调用
closeEntry()(否则可能跳过后续条目)
注意编码与中文文件名问题
ZipInputStream 默认按系统平台编码(如 Windows 上是 GBK)解析条目名,若 ZIP 是用 UTF-8 创建(常见于 macOS/Linux/新版压缩工具),会导致中文路径乱码甚至 ZipException: invalid CEN header。
- JDK 7+ 可用
ZipInputStream(ReadableByteChannel, Charset)构造器指定编码(如StandardCharsets.UTF_8) - 更稳妥方式:改用
java.util.zip.ZipFile(支持Charset参数),或第三方库如org.apache.commons.compress - 避免依赖默认编码,尤其在跨平台部署时
安全解压:防止路径遍历攻击
恶意 ZIP 可能包含 ../ 路径(如 ../../../etc/passwd),直接拼接解压会覆盖系统文件。
- 对每个
ZipEntry.getName()做规范化校验:用Paths.get(entryName).normalize()得到标准路径 - 检查标准化后路径是否仍以目标解压根目录为前缀(如
targetDir.toPath().resolve(normalizedPath).startsWith(targetDir.toPath())) - 拒绝含
".."、以"/"开头、或含控制字符的条目名 - 不信任 ZIP 内部路径,始终以安全方式构造本地文件路径
完整示例(JDK 8+,含 UTF-8 支持与路径校验)
以下代码解压 ZIP 到指定目录,自动处理中文名、跳过目录、防御路径穿越:
public static void unzip(InputStream zipInput, Path targetDir) throws IOException {
try (ZipInputStream zis = new ZipInputStream(zipInput, StandardCharsets.UTF_8)) {
Files.createDirectories(targetDir);
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
Path resolved = targetDir.resolve(entry.getName()).normalize();
if (!resolved.startsWith(targetDir)) {
throw new IOException("Bad zip entry: " + entry.getName());
}
if (entry.isDirectory()) {
Files.createDirectories(resolved);
} else {
Files.createDirectories(resolved.getParent());
Files.copy(zis, resolved, StandardCopyOption.REPLACE_EXISTING);
}
zis.closeEntry();
}
}
}
调用:unzip(Files.newInputStream(Paths.get("data.zip")), Paths.get("./output"))
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











