C#向现有ZIP包添加文件 C#如何更新一个zip压缩文件

来源:这里教程网 时间:2026-02-21 17:42:55 作者:

ZipArchive
打开 ZIP 时必须指定
ZipArchiveMode.Update

默认的

ZipArchive
构造方式(如只传
Stream
)是只读模式,直接调用
CreateEntry
会抛出
NotSupportedException
。必须显式传入
ZipArchiveMode.Update
,且底层流不能是只读的(比如
File.OpenRead()
就不行)。

使用
File.Open(..., FileMode.Open, FileAccess.ReadWrite)
File.Open(..., FileMode.OpenOrCreate, FileAccess.ReadWrite)
如果 ZIP 文件不存在,
FileMode.Open
会抛
FileNotFoundException
,建议先检查文件是否存在,再选
OpenOrCreate
别用
MemoryStream
做更新目标——它不支持随机写入,
ZipArchiveMode.Update
会失败

ZipArchive.CreateEntry
会覆盖同名文件,但不会自动删除旧条目

ZIP 是基于条目(entry)的扁平结构,没有“目录”概念;添加同名路径的 entry 时,

CreateEntry
不报错,但后续写入会覆盖该路径的内容。但注意:原 ZIP 中已存在的同名 entry 并不会被自动清理——实际效果取决于 ZIP 工具如何解析重复路径(多数解压工具取最后一个)。真正安全的更新需手动删除旧 entry。

遍历
archive.Entries
,用
entry.FullName.Equals("path/in/zip.txt", StringComparison.OrdinalIgnoreCase)
查找
调用
entry.Delete()
(仅在
Update
模式下可用)
CreateEntry
+ 写入新内容
注意:.NET 6+ 支持
Delete()
;.NET 5 及更早版本不支持,只能重建整个 ZIP

写入内容后必须显式调用
stream.Flush()
archive.Dispose()

ZipArchive
的更新是延迟写入的:entry 创建、流写入都不立即落盘。只有在
Dispose()
(或
using
块结束)时才真正重写 ZIP 文件头和中央目录。漏掉这步会导致 ZIP 损坏或新增文件不可见。

务必用
using (var archive = new ZipArchive(stream, ZipArchiveMode.Update)) { ... }
不要提前
stream.Close()
stream.Dispose()
,否则
archive.Dispose()
会失败
如果手写
try/finally
,确保
archive.Dispose()
finally
中执行

追加文件时路径分隔符必须用正斜杠
/

ZIP 规范要求内部路径使用

/
,即使在 Windows 上用
Path.Combine
生成的是
,也会导致解压时路径异常(如创建出名为 
"folderile.txt"
的单个文件,而非子目录结构)。

entryName.Replace("\", "/")
Path.GetRelativePath(root, fullPath).Replace("\", "/")
避免以
/
开头(如
/data/file.txt
),ZIP 解析器可能忽略前导斜杠,导致路径错位
空目录无法直接添加——ZIP 没有目录 entry,只能靠文件路径隐含,例如
"logs/"
不合法,但
"logs/empty.txt"
可以让解压工具创建
logs
目录
.NET 的 ZIP 更新能力很基础,不支持压缩级别调整、加密、跨磁盘追加等操作;真要高频修改 ZIP,不如用
SharpZipLib
DotNetZip
这类库——它们暴露更多控制点,但代价是引入第三方依赖。

相关推荐

热文推荐