Class ZipUtil

java.lang.Object
cloud.opencode.base.io.compress.ZipUtil

public final class ZipUtil extends Object
Zip Archive Utility Zip归档工具类

Provides static utility methods for creating, extracting, and inspecting Zip archives. Includes security protections against zip bombs and path traversal attacks.

提供创建、提取和检查Zip归档的静态工具方法。 包含针对zip炸弹和路径穿越攻击的安全保护。

Features | 主要功能:

  • Zip files and directories - 压缩文件和目录
  • Extract zip archives safely - 安全提取zip归档
  • List and read individual entries - 列出和读取单个条目
  • Fluent builder API for complex archives - 复杂归档的流式构建器API
  • Path traversal protection - 路径穿越防护
  • Zip bomb protection - Zip炸弹防护

Usage Examples | 使用示例:

// Zip a directory
ZipUtil.zip(sourceDir, targetZip);

// Unzip safely
ZipUtil.unzip(zipFile, outputDir);

// List entries
List<ZipEntryInfo> entries = ZipUtil.list(zipFile);

// Builder API
ZipUtil.builder()
    .addFile(path1)
    .addString("note.txt", "hello")
    .writeTo(outputZip);

Security | 安全性:

  • Thread-safe: Yes (stateless utility class) - 线程安全: 是(无状态工具类)
  • Path traversal: Blocked - 路径穿越: 已阻止
  • Zip bomb: Size and entry count limits - Zip炸弹: 大小和条目数限制
Since:
JDK 25, opencode-base-io V1.0.3
Author:
Leon Soo www.LeonSoo.com
See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final int
    Maximum number of entries allowed in a zip archive Zip归档中允许的最大条目数
    static final int
    Maximum entry name length allowed 允许的最大条目名长度
    static final long
    Maximum total uncompressed size allowed (4GB) 允许的最大总未压缩大小(4GB)
  • Method Summary

    Modifier and Type
    Method
    Description
    static ZipBuilder
    Creates a new fluent builder for assembling a zip archive 创建一个新的流式构建器用于组装zip归档
    static ZipResult
    compress(Path zipFile, Collection<Path> sources, ZipOptions options)
    Compresses sources into a ZIP using ZipOptions (compression level, exclude globs, encoding, etc.) and returns aggregated statistics.
    static void
    Streams entries into the supplied output as a ZIP archive without staging to disk.
    static boolean
    containsEntry(Path zipFile, String entryName)
    Checks whether a zip archive contains an entry with the given name 检查zip归档中是否包含给定名称的条目
    static ZipResult
    extract(Path zipFile, Path targetDir, ZipOptions options)
    Extracts a ZIP using ZipOptions (overwrite policy, anti-bomb thresholds) and returns aggregated statistics.
    static ZipResult
    extractMatching(Path zipFile, Path targetDir, List<String> patterns)
    Extracts entries whose names match any of the supplied glob patterns.
    static ZipResult
    extractMatching(Path zipFile, Path targetDir, List<String> patterns, ZipOptions options)
    Extracts entries whose names match any of the supplied glob patterns, with custom options.
    list(Path zipFile)
    Lists all entries in a zip archive 列出zip归档中的所有条目
    openEntry(Path zipFile, String entryName)
    Opens a streaming InputStream for a single ZIP entry.
    static byte[]
    readEntry(Path zipFile, String entryName)
    Reads a single entry from a zip archive 从zip归档中读取单个条目
    static byte[]
    readEntry(Path zipFile, String entryName, long maxSize)
    Reads a single entry from a zip archive with a size limit 从zip归档中读取单个条目(带大小限制)
    static void
    unzip(Path zipFile, Path targetDir)
    Extracts a zip archive to the target directory with security checks 使用安全检查将zip归档提取到目标目录
    static void
    zip(Path source, Path target)
    Zips a single file or directory to the target zip file 将单个文件或目录压缩到目标zip文件
    static void
    zip(Collection<Path> sources, Path target)
    Zips multiple files to the target zip file 将多个文件压缩到目标zip文件

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • MAX_ENTRIES

      public static final int MAX_ENTRIES
      Maximum number of entries allowed in a zip archive Zip归档中允许的最大条目数
      See Also:
    • MAX_UNCOMPRESSED_SIZE

      public static final long MAX_UNCOMPRESSED_SIZE
      Maximum total uncompressed size allowed (4GB) 允许的最大总未压缩大小(4GB)
      See Also:
    • MAX_ENTRY_NAME_LENGTH

      public static final int MAX_ENTRY_NAME_LENGTH
      Maximum entry name length allowed 允许的最大条目名长度
      See Also:
  • Method Details

    • zip

      public static void zip(Path source, Path target)
      Zips a single file or directory to the target zip file 将单个文件或目录压缩到目标zip文件

      If source is a directory, its contents are added recursively.

      如果源是目录,则递归添加其内容。

      Parameters:
      source - the source file or directory | 源文件或目录
      target - the target zip file path | 目标zip文件路径
      Throws:
      NullPointerException - if source or target is null | 当source或target为null时抛出
      OpenIOOperationException - if zipping fails | 当压缩失败时抛出
    • zip

      public static void zip(Collection<Path> sources, Path target)
      Zips multiple files to the target zip file 将多个文件压缩到目标zip文件
      Parameters:
      sources - the source files | 源文件集合
      target - the target zip file path | 目标zip文件路径
      Throws:
      NullPointerException - if sources or target is null | 当sources或target为null时抛出
      OpenIOOperationException - if zipping fails | 当压缩失败时抛出
    • unzip

      public static void unzip(Path zipFile, Path targetDir)
      Extracts a zip archive to the target directory with security checks 使用安全检查将zip归档提取到目标目录

      Security protections applied:

      Parameters:
      zipFile - the zip file to extract | 要提取的zip文件
      targetDir - the target directory | 目标目录
      Throws:
      NullPointerException - if zipFile or targetDir is null | 当zipFile或targetDir为null时抛出
      OpenIOOperationException - if extraction fails or security check fails | 当提取失败或安全检查失败时抛出
    • list

      public static List<ZipEntryInfo> list(Path zipFile)
      Lists all entries in a zip archive 列出zip归档中的所有条目
      Parameters:
      zipFile - the zip file path | zip文件路径
      Returns:
      list of entry metadata | 条目元数据列表
      Throws:
      NullPointerException - if zipFile is null | 当zipFile为null时抛出
      OpenIOOperationException - if reading fails | 当读取失败时抛出
    • readEntry

      public static byte[] readEntry(Path zipFile, String entryName)
      Reads a single entry from a zip archive 从zip归档中读取单个条目
      Parameters:
      zipFile - the zip file path | zip文件路径
      entryName - the entry name to read | 要读取的条目名
      Returns:
      the entry data | 条目数据
      Throws:
      NullPointerException - if zipFile or entryName is null | 当zipFile或entryName为null时抛出
      OpenIOOperationException - if entry not found or reading fails | 当条目未找到或读取失败时抛出
    • readEntry

      public static byte[] readEntry(Path zipFile, String entryName, long maxSize)
      Reads a single entry from a zip archive with a size limit 从zip归档中读取单个条目(带大小限制)
      Parameters:
      zipFile - the zip file path | zip文件路径
      entryName - the entry name to read | 要读取的条目名
      maxSize - the maximum entry size in bytes | 最大条目大小(字节)
      Returns:
      the entry data | 条目数据
      Throws:
      NullPointerException - if zipFile or entryName is null | 当zipFile或entryName为null时抛出
      IllegalArgumentException - if maxSize is not positive | 当maxSize非正数时抛出
      OpenIOOperationException - if entry not found, reading fails, or size limit exceeded | 当条目未找到、读取失败或超出大小限制时抛出
    • containsEntry

      public static boolean containsEntry(Path zipFile, String entryName)
      Checks whether a zip archive contains an entry with the given name 检查zip归档中是否包含给定名称的条目
      Parameters:
      zipFile - the zip file path | zip文件路径
      entryName - the entry name to check | 要检查的条目名
      Returns:
      true if the entry exists | 如果条目存在返回true
      Throws:
      NullPointerException - if zipFile or entryName is null | 当zipFile或entryName为null时抛出
      OpenIOOperationException - if reading the zip fails | 当读取zip失败时抛出
    • builder

      public static ZipBuilder builder()
      Creates a new fluent builder for assembling a zip archive 创建一个新的流式构建器用于组装zip归档
      Returns:
      a new ZipBuilder | 新的ZipBuilder
    • compress

      public static ZipResult compress(Path zipFile, Collection<Path> sources, ZipOptions options)
      Compresses sources into a ZIP using ZipOptions (compression level, exclude globs, encoding, etc.) and returns aggregated statistics. 使用 ZipOptions(压缩级别、排除 glob、编码等)压缩源到 ZIP,并返回汇总统计。
      Parameters:
      zipFile - output ZIP path | 输出 ZIP 路径
      sources - files / directories to compress | 待压缩的文件 / 目录集合
      options - compression options | 压缩选项
      Returns:
      aggregated ZipResult | 汇总 ZipResult
      Throws:
      NullPointerException - when any argument is null | 任一参数为 null 时
      OpenIOOperationException - when compression fails | 压缩失败时
      Since:
      opencode-base-io V1.0.4
    • extract

      public static ZipResult extract(Path zipFile, Path targetDir, ZipOptions options)
      Extracts a ZIP using ZipOptions (overwrite policy, anti-bomb thresholds) and returns aggregated statistics. 使用 ZipOptions(覆盖策略、反炸弹阈值等)解压 ZIP,并返回汇总统计。

      Nested-ZIP detection note | 嵌套 ZIP 检测说明: the maxNestingDepth cap is enforced by checking that entry names end with .zip (case-insensitive); we do NOT magic-byte sniff entry payloads. An attacker who renames a nested archive (e.g. data.bin) bypasses this filter — treat the cap as a hardening hint rather than a complete defense. Use the size / count / ratio caps for stronger guarantees.

      maxNestingDepth 上限通过检查条目名后缀 .zip(不区分大小写)来生效; 不会对条目负载做魔数嗅探。攻击者把嵌套归档改名(如 data.bin)即可绕过本过滤; 把该上限视为加固提示而非完整防御,更强保证应靠大小/条目数/压缩比上限。

      Parameters:
      zipFile - ZIP file path | ZIP 文件路径
      targetDir - target directory | 目标目录
      options - extraction options | 解压选项
      Returns:
      aggregated ZipResult | 汇总 ZipResult
      Throws:
      NullPointerException - when any argument is null | 任一参数为 null 时
      ZipBombDetectedException - when anti-bomb thresholds are breached | 触发反炸弹阈值时
      OpenIOOperationException - when extraction fails | 解压失败时
      Since:
      opencode-base-io V1.0.4
    • extractMatching

      public static ZipResult extractMatching(Path zipFile, Path targetDir, List<String> patterns)
      Extracts entries whose names match any of the supplied glob patterns. 解压名称匹配任一 glob 模式的条目。

      Glob matching note | glob 匹配说明: each pattern is tested against BOTH the full entry path AND the file-name leaf to remain lenient with simple "*.log" style patterns. Callers wanting strict path matching (no leaf fallback) should use "&#42;&#42;/*.log" explicitly.

      每个模式同时对完整条目路径与叶子文件名匹配,兼容简单形式如 "*.log";需要严格 路径匹配(不走叶子兜底)时请显式使用 "&#42;&#42;/*.log"

      Parameters:
      zipFile - ZIP file path | ZIP 文件路径
      targetDir - target directory | 目标目录
      patterns - glob patterns to match | glob 模式
      Returns:
      aggregated ZipResult | 汇总 ZipResult
      Since:
      opencode-base-io V1.0.4
    • extractMatching

      public static ZipResult extractMatching(Path zipFile, Path targetDir, List<String> patterns, ZipOptions options)
      Extracts entries whose names match any of the supplied glob patterns, with custom options. 使用自定义选项解压名称匹配任一 glob 模式的条目。
      Parameters:
      zipFile - ZIP file path | ZIP 文件路径
      targetDir - target directory | 目标目录
      patterns - glob patterns to match | glob 模式
      options - extraction options | 解压选项
      Returns:
      aggregated ZipResult | 汇总 ZipResult
      Since:
      opencode-base-io V1.0.4
    • openEntry

      public static InputStream openEntry(Path zipFile, String entryName)
      Opens a streaming InputStream for a single ZIP entry. The caller MUST close the returned stream; closing it also releases the underlying ZipFile. 打开单个 ZIP 条目的流式 InputStream。调用方必须关闭返回的流,关闭时同时释放底层 ZipFile
      Parameters:
      zipFile - ZIP file path | ZIP 文件路径
      entryName - entry name to open | 要打开的条目名
      Returns:
      streaming entry content | 条目流式内容
      Throws:
      NullPointerException - when any argument is null | 任一参数为 null 时
      OpenIOOperationException - when the entry is missing or read fails | 条目缺失或读取失败时
      Since:
      opencode-base-io V1.0.4
    • compressStream

      public static void compressStream(OutputStream output, List<ZipEntrySource> entries, ZipOptions options)
      Streams entries into the supplied output as a ZIP archive without staging to disk. 直接把流式条目写入给定输出,构建 ZIP 而无需先落盘。
      Parameters:
      output - output stream to write the ZIP to | 接收 ZIP 数据的输出流
      entries - entry sources | 流式条目
      options - compression options | 压缩选项
      Throws:
      NullPointerException - when any argument is null | 任一参数为 null 时
      OpenIOOperationException - when writing fails | 写入失败时
      Since:
      opencode-base-io V1.0.4