使用ZipOutputStream打包多个文件需为每个文件创建独立ZipEntry并写入内容,注意路径处理、编码兼容、时间戳设置及资源释放。

使用 ZipOutputStream 打包多个文件,核心是为每个文件创建一个 ZipEntry,然后把文件内容写入流中。关键点在于:不能直接写入原始文件字节而不设置条目,也不能重复使用同一个 ZipEntry 对象。
准备待压缩的文件列表
先收集所有要压缩的文件(或目录),确保路径合法、可读。建议统一用 Path 操作,避免手动拼接路径出错:
- 如果是单个目录,需递归遍历所有普通文件
- 跳过目录本身(
Files.isDirectory())、符号链接(可选)、不可读文件 - 记录每个文件在 ZIP 包内的相对路径(如
docs/readme.txt),避免绝对路径
创建 ZipOutputStream 并逐个写入文件
用 FileOutputStream 包裹 ZipOutputStream,每处理一个文件前新建一个 ZipEntry,设置其名称(注意用正斜杠 / 分隔,且不能以 / 开头):
ZipEntry entry = new ZipEntry("subdir/file.txt");- 调用
zos.putNextEntry(entry)启动该条目写入 - 用
Files.copy(file, zos)或传统InputStream+read/write循环写入内容 - 必须调用
zos.closeEntry()结束当前条目(否则 ZIP 格式损坏)
注意时间戳、编码与资源释放
ZipEntry 默认时间戳是打包时刻,可用 entry.setTime(Files.getLastModifiedTime(path).toMillis()) 保留原修改时间;ZIP 规范默认使用 IBM437 编码,中文名可能乱码,Java 7+ 的 ZipOutputStream 在 UTF-8 环境下通常能正确处理(若需兼容旧系统,考虑用 org.apache.commons.compress):
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
- 务必用 try-with-resources 自动关闭
ZipOutputStream和底层FileOutputStream - 不要在循环内 new 多个
ZipOutputStream,一个流对应整个 ZIP 包 - 空目录如需保留,可手动添加名称结尾为
/的ZipEntry(并调用closeEntry)
简单示例片段(不依赖第三方库)
以下代码将 srcFiles 中的多个 Path 压缩到 output.zip:
try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(Paths.get("output.zip")))) {
for (Path file : srcFiles) {
String entryName = computeRelativePath(file); // 如 "data/log.txt"
ZipEntry entry = new ZipEntry(entryName);
entry.setTime(Files.getLastModifiedTime(file).toMillis());
zos.putNextEntry(entry);
Files.copy(file, zos);
zos.closeEntry();
}
}
不复杂但容易忽略细节。

















