Class ZipModifier
Both operations work by streaming the original archive into a sibling temporary file, applying the change, then atomically replacing the original. This keeps memory bounded and avoids leaving the archive in a partially-modified state if the JVM crashes mid-operation.
两个操作都通过把原归档流式拷贝到同目录临时文件后应用变更,再原子替换原文件。这样内存占用稳定, JVM 崩溃也不会把归档留在半改状态。
Thread safety | 线程安全: stateless static utility, safe for concurrent use on different archives. Concurrent operations on the SAME archive are NOT serialized — callers must synchronise externally if multiple threads might modify the same file. / 无状态静态工具,对不同归档可并发使用;对同一归档的并发操作不做串行化,需调用方自行同步。
Bomb protection | 反炸弹防护: the zero-BombProtection overloads of
addEntries(Path, List) / removeEntries(Path, Collection) apply
BombProtection.defaults() during the copy phase. Archives that exceed the default caps
(65535 entries, 10 GiB total, 100:1 ratio, etc.) cannot be modified through the default
overloads. Enterprise use cases that legitimately exceed defaults should use the overloads
accepting an explicit BombProtection.
无 BombProtection 参数的 addEntries(Path, List) / removeEntries(Path, Collection)
重载会在拷贝阶段应用 BombProtection.defaults()。超过默认上限的归档无法通过这些重载修改,
企业级合法场景请使用接受 BombProtection 的重载。
- Since:
- JDK 25, opencode-base-io V1.0.4
- Author:
- Leon Soo www.LeonSoo.com
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionaddEntries(Path zipFile, Collection<Path> sources) Convenience overload accepting aCollectionofPath, equivalent to: 便捷重载,接受Path集合,等价于:ZipModifier.addEntries(zipFile, new ArrayList<>(sources)).addEntries(Path zipFile, Collection<Path> sources, BombProtection caps) Convenience overload ofaddEntries(Path, Collection)accepting an explicitBombProtectionpreset for the copy-existing-entries phase.addEntries(Path zipFile, List<Path> sources) Adds files to an existing ZIP archive with default bomb caps.addEntries(Path zipFile, List<Path> sources, BombProtection caps) Adds files to an existing ZIP archive.static intremoveEntries(Path zipFile, Collection<String> entryNames) Removes entries by name from an existing ZIP archive with default bomb caps.static intremoveEntries(Path zipFile, Collection<String> entryNames, BombProtection caps) Removes entries by name from an existing ZIP archive.static intremoveEntries(Path zipFile, List<String> entryNames) Convenience overload that adaptsListto theCollectionvariant.static intremoveEntries(Path zipFile, List<String> entryNames, BombProtection caps) Convenience overload ofremoveEntries(Path, List)accepting an explicitBombProtectionpreset for the copy-existing-entries phase.
-
Method Details
-
addEntries
Adds files to an existing ZIP archive with default bomb caps. Existing entries with the same names are replaced. Returns names of replaced entries for audit. 用默认反炸弹上限向已有 ZIP 追加文件;同名条目会被替换;返回被替换的条目名供审计。See
addEntries(Path, List, BombProtection)for the full contract; this overload delegates withBombProtection.defaults().完整契约见
addEntries(Path, List, BombProtection);此重载委托BombProtection.defaults()。- Parameters:
zipFile- target archive | 目标归档sources- files to add | 要添加的文件- Returns:
- names of entries replaced by this call | 本次被替换的条目名
-
addEntries
Adds files to an existing ZIP archive. Existing entries with the same names are replaced. Returns an unmodifiable list of entry names that were already present and got replaced by this call (empty when nothing was overwritten) — useful for audit logging. 向已有 ZIP 追加文件;同名条目会被替换。返回本次被替换的条目名(已存在并被覆盖), 无替换则返回空列表,便于审计日志。Cost note | 成本说明: Java's standard ZIP format does not support in-place append, so every call to
addEntriesstreams the entire existing archive to a temporary file and atomically renames over the original. Adding 1 KiB to a 1 GiB archive performs a 1 GiB rewrite. Callers needing batched insertion should accumulate paths and issue a singleaddEntries(zip, allPaths)rather than per-file calls.Java 标准 ZIP 不支持就地追加,每次调用
addEntries都会把整个原归档流式拷到临时 文件再原子替换。向 1 GiB 归档加 1 KiB 也要重写 1 GiB。调用方应累积所有路径后单次addEntries(zip, allPaths),避免逐文件调用。Audit return reliability | 审计返回的可靠性: the returned list is best-effort. If reading the existing archive's central directory fails (e.g. NFS blip during the audit pre-scan), the implementation returns an empty list rather than propagating the read error — the actual write phase that follows will throw if the archive is truly unreadable. So an empty list means EITHER (a) genuinely nothing was replaced, OR (b) the audit pre-scan failed silently. Callers needing strict-audit semantics should call
ZipUtil.list(Path)themselves beforeaddEntriesand compare.返回列表为尽力(best-effort)契约。若在审计预扫描时读取中央目录失败(如 NFS 抖动), 实现返回空列表而不是抛出读错误 —— 紧接着的写阶段如果归档真的不可读自然会抛出。 因此空列表既可能表示(a)确实没有替换,也可能表示(b)审计预扫描静默失败。需要严格审计 语义时,请调用方自行先
ZipUtil.list(Path)后再addEntries并对比。- Parameters:
zipFile- target archive | 目标归档sources- files to add (each top-level path becomes one entry by file name; directories are walked recursively and contained files become entries with paths relative to the directory) | 要添加的文件(每个顶层路径以文件名作为一个条目;目录递归 展开,包含文件以相对目录的路径作为条目名)caps- bomb-protection caps applied while copying the existing archive | 拷贝原归档阶段应用的反炸弹上限- Returns:
- names of entries that were replaced by this call (best-effort, see above) | 本次被替换的条目名(尽力契约,见上)
- Throws:
NullPointerException- when any argument is null | 任一参数为 null 时OpenIOOperationException- when modification fails | 修改失败时
-
removeEntries
Removes entries by name from an existing ZIP archive with default bomb caps. Names not present are silently ignored. 用默认反炸弹上限从已有 ZIP 删除指定名称的条目;不存在的名称会被静默忽略。See
removeEntries(Path, Collection, BombProtection)for the full contract.- Parameters:
zipFile- target archive | 目标归档entryNames- names to remove | 要删除的条目名- Returns:
- number of names that were actually present and removed (excludes silently-ignored missing names) | 实际存在并被删除的条目数(不计静默忽略的缺失名)
- Throws:
NullPointerException- when any argument is null | 任一参数为 null 时OpenIOOperationException- when modification fails | 修改失败时
-
removeEntries
Removes entries by name from an existing ZIP archive. Names not present are silently ignored. 从已有 ZIP 中按名称删除条目;不存在的名称会被静默忽略。- Parameters:
zipFile- target archive | 目标归档entryNames- names to remove | 要删除的条目名caps- bomb-protection caps applied while copying the existing archive | 拷贝原归档阶段应用的反炸弹上限- Returns:
- number of names that were actually present and removed | 实际存在并被删除的条目数
- Throws:
NullPointerException- when any argument is null | 任一参数为 null 时OpenIOOperationException- when modification fails | 修改失败时
-
removeEntries
- Parameters:
zipFile- target archive | 目标归档entryNames- names to remove | 要删除的条目名- Returns:
- number of names actually removed | 实际删除的条目数
-
removeEntries
Convenience overload ofremoveEntries(Path, List)accepting an explicitBombProtectionpreset for the copy-existing-entries phase.removeEntries(Path, List)的便捷重载,可显式传入用于拷贝现有条目阶段的BombProtection预设。- Parameters:
zipFile- target archive | 目标归档entryNames- names to remove | 要删除的条目名caps- bomb-protection caps | 反炸弹上限- Returns:
- number of names actually removed | 实际删除的条目数
- Since:
- opencode-base-io V1.0.4
-
addEntries
Convenience overload accepting aCollectionofPath, equivalent to: 便捷重载,接受Path集合,等价于:ZipModifier.addEntries(zipFile, new ArrayList<>(sources)).- Parameters:
zipFile- target archive | 目标归档sources- files to add | 要添加的文件- Returns:
- names of replaced entries | 被替换的条目名
-
addEntries
Convenience overload ofaddEntries(Path, Collection)accepting an explicitBombProtectionpreset for the copy-existing-entries phase.addEntries(Path, Collection)的便捷重载,可显式传入用于拷贝现有条目阶段的BombProtection预设。- Parameters:
zipFile- target archive | 目标归档sources- files to add | 要添加的文件caps- bomb-protection caps | 反炸弹上限- Returns:
- names of replaced entries | 被替换的条目名
- Since:
- opencode-base-io V1.0.4
-