ZIP工具-ZipUtil
# 📚 介绍
ZipUtil 是 Hutool 压缩模块的核心工具类,提供了丰富的 ZIP 压缩和解压缩功能,是对 JDK java.util.zip 包的高级封装。它简化了 ZIP 文件的创建、读取和修改操作,让开发者可以用更少的代码完成复杂的 ZIP 处理任务。
# 设计理念
- 简化API:提供简洁易用的静态方法,减少样板代码
- 全面覆盖:支持 ZIP 文件的创建、解压、读取、修改等各种操作
- 资源安全:自动处理流的打开和关闭,避免资源泄漏
- 灵活扩展:支持多种压缩和解压选项
- 高性能:底层实现经过优化,性能优异
- 线程安全:所有方法都是线程安全的,可以在多线程环境下安全使用
# 🔧 核心方法详解
# 1. ZIP压缩
# zip(String src, String dest)
功能:将文件或目录压缩为 ZIP 文件
参数:
src:源文件或目录路径dest:目标 ZIP 文件路径
返回值:生成的 ZIP 文件对象
示例:
// 压缩单个文件
File zipFile1 = ZipUtil.zip("source.txt", "source.zip");
Console.log("压缩文件生成:" + zipFile1.getAbsolutePath());
// 压缩目录
File zipFile2 = ZipUtil.zip("sourceDir", "sourceDir.zip");
Console.log("压缩目录生成:" + zipFile2.getAbsolutePath());
# zip(String dest, boolean isDir, String... srcFiles)
功能:将多个文件或目录压缩为 ZIP 文件
参数:
dest:目标 ZIP 文件路径isDir:是否将所有源路径作为一个目录压缩srcFiles:源文件或目录路径数组
返回值:生成的 ZIP 文件对象
示例:
// 压缩多个文件到一个 ZIP 中
File zipFile = ZipUtil.zip("output.zip", false, "file1.txt", "file2.txt", "file3.txt");
Console.log("压缩文件生成:" + zipFile.getAbsolutePath());
// 将多个文件作为一个目录压缩
File zipFile2 = ZipUtil.zip("output2.zip", true, "file1.txt", "file2.txt");
Console.log("压缩文件生成:" + zipFile2.getAbsolutePath());
# zip(String src, String dest, Filter pathFilter)
功能:将文件或目录压缩为 ZIP 文件,支持路径过滤
参数:
src:源文件或目录路径dest:目标 ZIP 文件路径pathFilter:路径过滤器,用于排除不需要压缩的文件
返回值:生成的 ZIP 文件对象
示例:
// 压缩目录,排除临时文件和隐藏文件
File zipFile = ZipUtil.zip("sourceDir", "sourceDir.zip", path -> {
String fileName = path.getFileName().toString();
// 排除临时文件和隐藏文件
return !fileName.endsWith(".tmp") && !fileName.startsWith(".");
});
Console.log("压缩文件生成:" + zipFile.getAbsolutePath());
# 2. ZIP解压
# unzip(String zipFile, String destDir)
功能:解压 ZIP 文件到指定目录
参数:
zipFile:ZIP 文件路径destDir:目标目录路径
返回值:解压后的目录对象
示例:
// 解压 ZIP 文件到指定目录
File destDir = ZipUtil.unzip("source.zip", "outputDir");
Console.log("解压完成,目标目录:" + destDir.getAbsolutePath());
# unzip(String zipFile)
功能:解压 ZIP 文件到当前目录
参数:
zipFile:ZIP 文件路径
返回值:解压后的目录对象
示例:
// 解压 ZIP 文件到当前目录
File destDir = ZipUtil.unzip("source.zip");
Console.log("解压完成,目标目录:" + destDir.getAbsolutePath());
# unzipFile(String zipFile, String destDir, String fileName)
功能:从 ZIP 文件中解压指定文件
参数:
zipFile:ZIP 文件路径destDir:目标目录路径fileName:要解压的文件名
返回值:解压后的文件对象
示例:
// 从 ZIP 文件中解压指定文件
File extractedFile = ZipUtil.unzipFile("source.zip", "outputDir", "file.txt");
Console.log("文件解压完成:" + extractedFile.getAbsolutePath());
# 3. ZIP文件读取
# reader(String zipFile)
功能:创建 ZIP 文件读取器
参数:
zipFile:ZIP 文件路径
返回值:ZIP 文件读取器
示例:
// 创建 ZIP 读取器
try (ZipReader reader = ZipUtil.reader("source.zip")) {
// 获取所有 ZIP 条目
List<ZipEntry> entries = reader.getEntries();
Console.log("ZIP 包含 " + entries.size() + " 个条目:");
// 遍历所有条目
for (ZipEntry entry : entries) {
Console.log("- " + entry.getName() + " (" + entry.getSize() + " bytes)");
}
// 读取指定文件内容
if (reader.contains("file.txt")) {
String content = reader.readStr("file.txt");
Console.log("file.txt 内容:\n" + content);
}
} catch (IOException e) {
e.printStackTrace();
}
# reader(File zipFile)
功能:从文件对象创建 ZIP 文件读取器
参数:
zipFile:ZIP 文件对象
返回值:ZIP 文件读取器
示例:
File zipFile = new File("source.zip");
try (ZipReader reader = ZipUtil.reader(zipFile)) {
// 使用读取器进行操作
// ...
} catch (IOException e) {
e.printStackTrace();
}
# 4. ZIP文件写入
# writer(String zipFile)
功能:创建 ZIP 文件写入器
参数:
zipFile:ZIP 文件路径
返回值:ZIP 文件写入器
示例:
// 创建 ZIP 写入器
try (ZipWriter writer = ZipUtil.writer("output.zip")) {
// 写入文件
writer.add("file1.txt");
// 写入目录
writer.add("sourceDir");
// 写入字节数组
writer.add("content.txt", "Hello Hutool".getBytes(CharsetUtil.CHARSET_UTF_8));
// 写入字符串
writer.add("text.txt", "This is a test", CharsetUtil.CHARSET_UTF_8);
Console.log("ZIP 文件写入完成");
} catch (IOException e) {
e.printStackTrace();
}
# writer(File zipFile)
功能:从文件对象创建 ZIP 文件写入器
参数:
zipFile:ZIP 文件对象
返回值:ZIP 文件写入器
示例:
File zipFile = new File("output.zip");
try (ZipWriter writer = ZipUtil.writer(zipFile)) {
// 使用写入器进行操作
// ...
} catch (IOException e) {
e.printStackTrace();
}
# 5. 其他辅助方法
# contains(String zipFile, String entryName)
功能:检查 ZIP 文件是否包含指定条目
参数:
zipFile:ZIP 文件路径entryName:条目名称
返回值:如果包含指定条目则返回 true,否则返回 false
示例:
// 检查 ZIP 文件是否包含指定条目
boolean contains = ZipUtil.contains("source.zip", "file.txt");
Console.log("ZIP 包含 file.txt:" + contains);
# listFileNames(String zipFile)
功能:获取 ZIP 文件中所有条目的名称
参数:
zipFile:ZIP 文件路径
返回值:ZIP 文件中所有条目的名称列表
示例:
// 获取 ZIP 文件中所有条目的名称
List<String> fileNames = ZipUtil.listFileNames("source.zip");
Console.log("ZIP 包含以下文件:");
for (String fileName : fileNames) {
Console.log("- " + fileName);
}
# 🚀 综合示例
# 示例1:ZIP文件的创建与解压
public class ZipCreateAndExtractTest {
public static void main(String[] args) {
// 1. 创建测试文件和目录
createTestFiles();
Console.log("=== 开始测试 ZIP 压缩和解压 ===");
// 2. 压缩单个文件
Console.log("1. 压缩单个文件");
File zipFile1 = ZipUtil.zip("test\file1.txt", "test\file1.zip");
Console.log(" 压缩完成:" + zipFile1.getAbsolutePath());
// 3. 压缩目录
Console.log("2. 压缩目录");
File zipFile2 = ZipUtil.zip("test\subdir", "test\subdir.zip");
Console.log(" 压缩完成:" + zipFile2.getAbsolutePath());
// 4. 压缩多个文件
Console.log("3. 压缩多个文件");
File zipFile3 = ZipUtil.zip("test\multi.zip", false, "test\file1.txt", "test\file2.txt");
Console.log(" 压缩完成:" + zipFile3.getAbsolutePath());
// 5. 过滤压缩(排除临时文件)
Console.log("4. 过滤压缩(排除临时文件)");
File zipFile4 = ZipUtil.zip("test", "test\filtered.zip", path -> !path.toString().endsWith(".tmp"));
Console.log(" 压缩完成:" + zipFile4.getAbsolutePath());
// 6. 解压 ZIP 文件
Console.log("5. 解压 ZIP 文件");
File destDir1 = ZipUtil.unzip("test\file1.zip", "test\extract1");
Console.log(" 解压完成:" + destDir1.getAbsolutePath());
// 7. 解压指定文件
Console.log("6. 解压指定文件");
File extractedFile = ZipUtil.unzipFile("test\multi.zip", "test\extract2", "file1.txt");
Console.log(" 解压完成:" + extractedFile.getAbsolutePath());
Console.log("=== ZIP 压缩和解压测试完成 ===");
}
private static void createTestFiles() {
// 创建测试目录结构
File testDir = new File("test");
File subDir = new File("test\subdir");
if (!testDir.exists()) testDir.mkdirs();
if (!subDir.exists()) subDir.mkdirs();
try {
// 创建测试文件
FileUtil.writeUtf8String("This is file 1", new File("test\file1.txt"));
FileUtil.writeUtf8String("This is file 2", new File("test\file2.txt"));
FileUtil.writeUtf8String("This is temporary file", new File("test\temp.tmp"));
FileUtil.writeUtf8String("This is subdir file 1", new File("test\subdir\subfile1.txt"));
FileUtil.writeUtf8String("This is subdir file 2", new File("test\subdir\subfile2.txt"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
# 示例2:ZIP文件的读取与修改
public class ZipReadAndModifyTest {
public static void main(String[] args) {
// 1. 创建测试 ZIP 文件
createTestZip();
Console.log("=== 开始测试 ZIP 读取与修改 ===");
// 2. 读取 ZIP 文件内容
Console.log("1. 读取 ZIP 文件内容");
try (ZipReader reader = ZipUtil.reader("test\readtest.zip")) {
// 获取所有条目
List<ZipEntry> entries = reader.getEntries();
Console.log(" ZIP 包含 " + entries.size() + " 个条目:");
for (ZipEntry entry : entries) {
Console.log(" - " + entry.getName() + " (" + entry.getSize() + " bytes)");
}
// 读取指定文件内容
if (reader.contains("file1.txt")) {
String content = reader.readStr("file1.txt");
Console.log(" file1.txt 内容:\n" + content);
}
} catch (IOException e) {
e.printStackTrace();
}
// 3. 修改 ZIP 文件内容
Console.log("2. 修改 ZIP 文件内容");
try (ZipReplacer replacer = ZipUtil.replacer("test\readtest.zip")) {
// 添加新文件
replacer.add("newfile.txt", "This is a new file".getBytes(CharsetUtil.CHARSET_UTF_8));
// 修改现有文件
replacer.update("file1.txt", "This is modified content".getBytes(CharsetUtil.CHARSET_UTF_8));
// 删除文件
replacer.remove("file2.txt");
Console.log(" ZIP 文件修改完成");
} catch (IOException e) {
e.printStackTrace();
}
// 4. 验证修改结果
Console.log("3. 验证修改结果");
try (ZipReader reader = ZipUtil.reader("test\readtest.zip")) {
List<ZipEntry> entries = reader.getEntries();
Console.log(" 修改后 ZIP 包含 " + entries.size() + " 个条目:");
for (ZipEntry entry : entries) {
Console.log(" - " + entry.getName() + " (" + entry.getSize() + " bytes)");
}
} catch (IOException e) {
e.printStackTrace();
}
Console.log("=== ZIP 读取与修改测试完成 ===");
}
private static void createTestZip() {
try (ZipWriter writer = ZipUtil.writer("test\readtest.zip")) {
writer.add("file1.txt", "This is file 1".getBytes(CharsetUtil.CHARSET_UTF_8));
writer.add("file2.txt", "This is file 2".getBytes(CharsetUtil.CHARSET_UTF_8));
writer.add("subdir\subfile.txt", "This is subdir file".getBytes(CharsetUtil.CHARSET_UTF_8));
} catch (IOException e) {
e.printStackTrace();
}
}
}
# 🎯 设计优势
- 简洁易用:提供了简洁的 API,一行代码即可完成复杂的 ZIP 操作
- 全面覆盖:支持 ZIP 文件的创建、解压、读取、修改等各种操作
- 资源安全:自动处理流的打开和关闭,避免资源泄漏
- 灵活扩展:支持多种压缩和解压选项,如路径过滤、编码设置等
- 高性能:底层实现经过优化,性能优异
- 线程安全:所有方法都是线程安全的,可以在多线程环境下安全使用
- 良好的异常处理:统一处理异常,简化错误处理逻辑
- 与其他模块集成:与 FileUtil 等模块无缝集成,提供更强大的功能
# 📌 注意事项
- 文件编码:ZIP 文件名默认使用 UTF-8 编码,如果需要处理其他编码的 ZIP 文件,请使用相应的重载方法指定编码
- 大文件处理:对于超大文件,建议使用 ZipReader 和 ZipWriter 进行流式处理,避免内存溢出
- 性能考虑:压缩操作可能会消耗较多 CPU 和内存资源,建议在后台线程中执行
- 安全问题:处理不可信的 ZIP 文件时,注意防范 ZIP 炸弹等安全风险
- 临时文件:ZIP 操作过程中可能会生成临时文件,Hutool 会自动清理这些临时文件
- 目录结构:压缩目录时,注意保持正确的目录结构,避免文件路径混乱
# 🚀 总结
ZipUtil 是一个功能强大、使用便捷的 ZIP 工具类,为 Java 开发者提供了丰富的 ZIP 处理解决方案。它简化了 ZIP 文件的创建、解压、读取和修改操作,提高了开发效率,减少了样板代码。
无论是简单的单个文件压缩,还是复杂的 ZIP 文件内容修改,ZipUtil 都能提供便捷的解决方案。通过合理使用 ZipUtil,可以简化 ZIP 相关的开发工作,提高代码的可读性和可维护性。
ZipUtil 是 Hutool 压缩模块的核心组件,与其他压缩相关类一起,构成了完整的压缩解决方案,为 Java 开发者提供了强大的压缩工具支持。