C#中如何无需解压重压缩直接复制Zip归档内的压缩文件?
在C#中直接复用Zip压缩条目实现归档复制
当然有办法跳过解压重压缩的往返过程,直接复用已压缩条目完成归档复制,下面分几种方案说明:
.NET原生库的进阶操作
.NET自带的ZipArchive确实没有直接提供复制压缩条目的API,但可以通过直接操作归档流的方式实现——不过这需要你对Zip文件格式的结构有一定了解:
- 打开源Zip文件的只读流,定位到目标条目的原始压缩数据起始位置
- 通过
ZipArchiveEntry的CompressedLength属性获取压缩数据的长度,读取对应字节 - 创建目标
ZipArchive时,添加新条目并手动设置与源条目一致的压缩方式、CRC值、文件大小等元数据,最后把读取到的压缩字节直接写入
这种方式需要小心处理格式细节,避免生成损坏的归档文件。
SharpZipLib的正确用法
你之前没找到的方法其实是存在的,SharpZipLib支持直接读取压缩后的条目数据,不用先解压:
- 打开源Zip文件的
ZipFile实例,找到目标ZipEntry - 记录该条目的
Offset(压缩数据在流中的起始位置)、CompressedSize、Crc、CompressionMethod等元数据 - 将源文件流定位到
Offset位置,直接读取对应长度的压缩字节 - 打开目标
ZipFile实例,创建一个和源条目元数据完全一致的新ZipEntry,然后把读取到的压缩字节直接写入,全程不用调用解压方法
示例代码片段:
// 打开源归档 using var sourceStream = File.OpenRead("source.zip"); using var sourceZip = new ZipFile(sourceStream); var sourceEntry = sourceZip.GetEntry("target-file.txt"); // 初始化目标归档 using var targetStream = File.Create("target.zip"); using var targetZip = new ZipFile(targetStream); // 创建与源条目匹配的目标条目 var targetEntry = new ZipEntry(sourceEntry.Name) { CompressionMethod = sourceEntry.CompressionMethod, Crc = sourceEntry.Crc, Size = sourceEntry.Size, CompressedSize = sourceEntry.CompressedSize, DateTime = sourceEntry.DateTime }; // 读取源条目压缩数据 sourceStream.Seek(sourceEntry.Offset, SeekOrigin.Begin); var compressedData = new byte[sourceEntry.CompressedSize]; sourceStream.Read(compressedData, 0, compressedData.Length); // 写入目标归档 targetZip.AddRawEntry(targetEntry, new MemoryStream(compressedData)); targetZip.Close();
更省心的第三方库选择
如果不想手动处理格式细节,可以用Ionic.Zip(原DotNetZip),它直接提供了复制Zip条目的API,一行代码就能搞定复用压缩数据:
using (var sourceZip = ZipFile.Read("source.zip")) using (var targetZip = new ZipFile()) { var entry = sourceZip["target-file.txt"]; targetZip.AddEntry(entry); // 直接复用原始压缩数据 targetZip.Save("target.zip"); }
内容的提问来源于stack exchange,提问作者Medinoc
相关产品推荐
相关产品推荐

