Hutool Hutool
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
(opens new window)
🏡首页
📖指南
🎢最佳实践
💖支持
💡javaDoc (opens new window)
⏳更新记录 (opens new window)
  • 🍎gitee (opens new window)
  • 🍏github (opens new window)
  • 快速入门

  • 核心(hutool-core)

    • AI(Hutool-ai)

    • 注解(annotation)

    • 数组(array)

    • JavaBean(bean)

    • 缓存(cache)

    • 类加载器(classloader)

    • 编码解码(codec)

    • 集合(collection)

    • 比较器(comparator)

    • 压缩(compress)

      • 简介
      • ZIP工具-ZipUtil
      • GZIP工具-Gzip
      • DEFLATE工具-Deflate
      • ZIP读取器-ZipReader
        • 📚简介
        • 🏗️核心结构
          • 1. 类定义
          • 2. 核心属性
        • 🔧 API说明
          • 1. 创建ZipReader实例
          • of(File zipFile, Charset charset)
          • of(InputStream in, Charset charset)
          • 2. 设置ZipBomb防护
          • setMaxSizeDiff(int maxSizeDiff)
          • 3. 获取文件流
          • get(String path)
          • 4. 解压操作
          • readTo(File outFile)
          • readTo(File outFile, Predicate entryFilter)
          • 5. 遍历Zip条目
          • read(Consumer consumer)
          • 6. 资源关闭
          • close()
        • 🚀 使用示例
          • 1. 从文件创建ZipReader并解压
          • 2. 使用try-with-resources自动关闭
          • 3. 从输入流创建ZipReader
          • 4. 使用过滤器解压特定文件
          • 5. 遍历Zip条目
          • 6. 读取单个文件内容
          • 7. 调整ZipBomb防护设置
        • 🎯 设计优势
          • 1. 统一的API接口
          • 2. 安全的ZipBomb防护
          • 3. 灵活的过滤机制
          • 4. 自动资源管理
          • 5. 跨平台兼容
          • 6. 高效的流处理
        • 📌 注意事项
          • 1. 编码问题
          • 2. ZipBomb防护
          • 3. 资源关闭
          • 4. 大文件处理
          • 5. 路径安全
        • 🔄 与传统JDK方式的对比
          • 1. 传统JDK方式(复杂)
          • 2. Hutool方式(简洁)
        • 📚 相关文档
      • ZIP写入器-ZipWriter
      • ZIP替换工具-ZipReplacer
      • ZIP资源-ZipResource
      • ZIP64支持-Zip64
    • 类型转换(convert)

    • 数据(data)

    • 日期时间(date)

    • 异常(exception)

    • 函数(func)

    • IO流(io)

    • 语言特性(lang)

    • Map(map)

    • 数字数学(math)

    • 网络(net)

    • 对象池(pool)

    • 反射(reflect)

    • 正则(regex)

    • 服务提供(spi)

    • 聚合操作(stream)

    • 字符串文本(text)

    • 并发和线程(thread)

    • 树结构(tree)

    • 工具集合(util)

    • XML操作(xml)

  • 定时任务(hutool-cron)

  • 加密(hutool-crypto)

  • 数据库(hutool-db)

  • 扩展(hutool-extra)

  • HTTP(hutool-http)

  • 日志(hutool-log)

  • 配置文件(hutool-setting)

  • JSON(hutool-json)

  • Office办公(hutool-poi)

  • 套接字(hutool-socket)

  • GUI(hutool-swing)

  • 指南
  • 核心(hutool-core)
  • 压缩(compress)
Hutool
2026-01-15
目录

ZIP读取器-ZipReader

# 📚简介

ZipReader类是Hutool压缩模块中用于读取Zip文件或流的工具类,主要用于Zip文件的解压操作。它封装了JDK的ZipFile和ZipInputStream,提供了更简洁易用的API,支持从文件或流中读取Zip内容,并提供了ZipBomb防护机制。

# 🏗️核心结构

# 1. 类定义

public class ZipReader implements Closeable {
    private static final int DEFAULT_MAX_SIZE_DIFF = 100;
    private final ZipResource resource;
    private int maxSizeDiff = DEFAULT_MAX_SIZE_DIFF;
    // ...
}

# 2. 核心属性

属性名 类型 描述
resource ZipResource Zip资源,封装了Zip文件或流的访问
maxSizeDiff int 检查ZipBomb文件差异倍数,默认100,-1表示不检查
DEFAULT_MAX_SIZE_DIFF int 默认的ZipBomb检查差异倍数,值为100

# 🔧 API说明

# 1. 创建ZipReader实例

# of(File zipFile, Charset charset)

从Zip文件创建ZipReader实例。

参数说明:

  • zipFile:要读取的Zip文件
  • charset:编码方式,用于处理文件名和内容的编码

返回值:

  • ZipReader实例,用于链式调用

# of(InputStream in, Charset charset)

从输入流创建ZipReader实例。

参数说明:

  • in:Zip输入流,一般为文件输入流
  • charset:编码方式,用于处理文件名和内容的编码

返回值:

  • ZipReader实例,用于链式调用

# 2. 设置ZipBomb防护

# setMaxSizeDiff(int maxSizeDiff)

设置检查ZipBomb文件差异倍数,用于防止Zip炸弹攻击。

参数说明:

  • maxSizeDiff:差异倍数,-1表示不检查ZipBomb,默认100

返回值:

  • ZipReader实例,用于链式调用

说明:

  • ZipBomb是一种恶意压缩文件,解压后体积会急剧膨胀,可能导致系统资源耗尽
  • 设置合理的maxSizeDiff可以有效防止ZipBomb攻击
  • 差异倍数 = 解压后大小 / 压缩前大小

# 3. 获取文件流

# get(String path)

获取Zip文件中指定路径的文件流。

参数说明:

  • path:文件在Zip中的路径,相对于Zip根目录

返回值:

  • 文件输入流,可以读取文件内容

实现逻辑:

  • 如果是文件模式,直接获取Entry对应的流
  • 如果是流模式,遍历entry后,找到对应流返回

# 4. 解压操作

# readTo(File outFile)

将Zip文件解压到指定目录。

参数说明:

  • outFile:解压到的目标目录

返回值:

  • 解压的目录,即参数中的outFile

异常:

  • IORuntimeException:IO异常

# readTo(File outFile, Predicate<ZipEntry> entryFilter)

带过滤器的解压,只解压符合条件的文件。

参数说明:

  • outFile:解压到的目标目录
  • entryFilter:过滤器,只保留test()方法返回true的文件

返回值:

  • 解压的目录,即参数中的outFile

异常:

  • IORuntimeException:IO异常

# 5. 遍历Zip条目

# read(Consumer<ZipEntry> consumer)

读取并处理Zip文件中的每一个ZipEntry。

参数说明:

  • consumer:ZipEntry处理器,用于处理每个Zip条目

返回值:

  • ZipReader实例,用于链式调用

异常:

  • IORuntimeException:IO异常

# 6. 资源关闭

# close()

关闭ZipReader,释放资源。

异常:

  • IORuntimeException:IO异常

# 🚀 使用示例

# 1. 从文件创建ZipReader并解压

// 从文件创建ZipReader
ZipReader reader = ZipReader.of(FileUtil.file("test.zip"), CharsetUtil.CHARSET_UTF_8);
try {
    // 解压到指定目录
    File destDir = FileUtil.file("output");
    reader.readTo(destDir);
    Console.log("解压完成,解压到目录:{}", destDir.getAbsolutePath());
} finally {
    // 关闭资源
    reader.close();
}

# 2. 使用try-with-resources自动关闭

// 使用try-with-resources自动关闭资源
try (ZipReader reader = ZipReader.of(FileUtil.file("test.zip"), CharsetUtil.CHARSET_UTF_8)) {
    reader.readTo(FileUtil.file("output"));
    Console.log("解压完成!");
}

# 3. 从输入流创建ZipReader

// 从输入流创建ZipReader
try (InputStream in = FileUtil.getInputStream("test.zip");
     ZipReader reader = ZipReader.of(in, CharsetUtil.CHARSET_UTF_8)) {
    reader.readTo(FileUtil.file("output"));
    Console.log("从流解压完成!");
}

# 4. 使用过滤器解压特定文件

// 只解压txt文件
try (ZipReader reader = ZipReader.of(FileUtil.file("test.zip"), CharsetUtil.CHARSET_UTF_8)) {
    reader.readTo(FileUtil.file("output"), entry -> {
        // 只解压txt文件,排除目录
        return !entry.isDirectory() && entry.getName().endsWith(".txt");
    });
    Console.log("只解压txt文件完成!");
}

# 5. 遍历Zip条目

// 遍历Zip中的所有条目
try (ZipReader reader = ZipReader.of(FileUtil.file("test.zip"), CharsetUtil.CHARSET_UTF_8)) {
    reader.read(entry -> {
        Console.log("条目名:{}", entry.getName());
        Console.log("  大小:{}字节", entry.getSize());
        Console.log("  压缩大小:{}字节", entry.getCompressedSize());
        Console.log("  是目录:{}", entry.isDirectory());
    });
}

# 6. 读取单个文件内容

// 读取Zip中的单个文件内容
try (ZipReader reader = ZipReader.of(FileUtil.file("test.zip"), CharsetUtil.CHARSET_UTF_8)) {
    try (InputStream in = reader.get("test.txt")) {
        if (in != null) {
            String content = IoUtil.readUtf8(in);
            Console.log("文件内容:{}", content);
        } else {
            Console.log("文件不存在!");
        }
    }
}

# 7. 调整ZipBomb防护设置

// 调整ZipBomb防护设置
try (ZipReader reader = ZipReader.of(FileUtil.file("test.zip"), CharsetUtil.CHARSET_UTF_8)) {
    // 设置为200倍差异检查,或者-1表示不检查
    reader.setMaxSizeDiff(200);
    reader.readTo(FileUtil.file("output"));
    Console.log("使用自定义ZipBomb检查设置解压完成!");
}

# 🎯 设计优势

# 1. 统一的API接口

  • 封装了ZipFile和ZipInputStream的差异,提供统一的访问接口
  • 支持从文件或流创建ZipReader,适应不同场景
  • 链式调用设计,代码更简洁流畅

# 2. 安全的ZipBomb防护

  • 内置ZipBomb检测机制,默认检查差异倍数为100
  • 可自定义检查倍数,或完全关闭检查
  • 有效防止恶意压缩文件导致的系统资源耗尽

# 3. 灵活的过滤机制

  • 支持通过Predicate<ZipEntry>过滤要处理的文件
  • 可以根据文件名、大小、类型等条件进行过滤
  • 便于只处理需要的文件,提高效率

# 4. 自动资源管理

  • 实现了Closeable接口,可以配合try-with-resources使用
  • 自动关闭底层资源,避免资源泄漏
  • 统一的异常处理,简化上层代码

# 5. 跨平台兼容

  • 自动处理不同操作系统的路径差异
  • 修复了Windows系统下文件名包含特殊字符的问题
  • 防止路径遍历攻击(Zip Slip)

# 6. 高效的流处理

  • 内部使用高效的流处理机制
  • 支持大文件处理,不会内存溢出
  • 优化了Zip条目遍历和文件读取的性能

# 📌 注意事项

# 1. 编码问题

  • 确保使用正确的编码方式,特别是处理非UTF-8编码的Zip文件
  • 不同操作系统和压缩工具生成的Zip文件可能使用不同的编码
  • 建议显式指定编码,避免默认编码导致的乱码问题

# 2. ZipBomb防护

  • 默认开启ZipBomb检查,差异倍数为100
  • 对于合法的高压缩比文件,可以适当调整差异倍数
  • 对于可信来源的文件,可以关闭检查以提高性能

# 3. 资源关闭

  • 务必关闭ZipReader实例,释放系统资源
  • 建议使用try-with-resources语句自动管理资源
  • 不关闭资源可能导致文件句柄泄漏

# 4. 大文件处理

  • 对于超大Zip文件,建议使用流式处理
  • 避免一次性读取所有内容到内存
  • 可以使用过滤器只处理需要的文件

# 5. 路径安全

  • ZipReader内置了路径遍历攻击防护
  • 自动检查并修复不安全的文件路径
  • 确保解压文件不会超出目标目录

# 🔄 与传统JDK方式的对比

# 1. 传统JDK方式(复杂)

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

// 传统方式解压Zip文件
String zipFilePath = "test.zip";
String destDirPath = "output";

// 方法1:使用ZipFile
try (ZipFile zipFile = new ZipFile(zipFilePath, StandardCharsets.UTF_8)) {
    zipFile.stream().forEach(entry -> {
        try {
            File destFile = new File(destDirPath, entry.getName());
            if (entry.isDirectory()) {
                destFile.mkdirs();
            } else {
                destFile.getParentFile().mkdirs();
                try (var in = zipFile.getInputStream(entry);
                     var out = new FileOutputStream(destFile)) {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = in.read(buffer)) > 0) {
                        out.write(buffer, 0, len);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
} catch (IOException e) {
    e.printStackTrace();
}

// 方法2:使用ZipInputStream
try (ZipInputStream zis = new ZipInputStream(
         new FileInputStream(zipFilePath), StandardCharsets.UTF_8)) {
    ZipEntry entry;
    while ((entry = zis.getNextEntry()) != null) {
        File destFile = new File(destDirPath, entry.getName());
        if (entry.isDirectory()) {
            destFile.mkdirs();
        } else {
            destFile.getParentFile().mkdirs();
            try (var out = new FileOutputStream(destFile)) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = zis.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
            }
        }
        zis.closeEntry();
    }
} catch (IOException e) {
    e.printStackTrace();
}

# 2. Hutool方式(简洁)

import cn.hutool.v7.core.compress.ZipReader;
import cn.hutool.v7.core.io.FileUtil;
import cn.hutool.v7.core.util.Console;

// Hutool方式解压Zip文件
String zipFilePath = "test.zip";
String destDirPath = "output";

// 一行代码完成解压
try (ZipReader reader = ZipReader.of(FileUtil.file(zipFilePath), CharsetUtil.CHARSET_UTF_8)) {
    reader.readTo(FileUtil.file(destDirPath));
    Console.log("解压完成!");
}

// 带过滤器的解压
try (ZipReader reader = ZipReader.of(FileUtil.file(zipFilePath), CharsetUtil.CHARSET_UTF_8)) {
    reader.readTo(FileUtil.file(destDirPath), entry -> !entry.isDirectory());
    Console.log("只解压文件完成!");
}

# 📚 相关文档

  • 压缩模块简介
  • ZIP工具-ZipUtil
  • ZIP写入器-ZipWriter
  • ZIP替换工具-ZipReplacer
DEFLATE工具-Deflate
ZIP写入器-ZipWriter

← DEFLATE工具-Deflate ZIP写入器-ZipWriter→

Theme by Vdoing | Copyright © 2025-2026 Hutool | Apache-2.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式