最近遇到个新需求,要对压缩包内的数据进行更新。因为数据量不大,没有采用解压后重新打包的方式,直接采用了内存流进行处理。代码如下:
void ModifyZip(string zipFilePath)
{
byte[] zipBytes = File.ReadAllBytes(zipFilePath);
// 读取 ZIP 文件到内存流
using (MemoryStream zipStream = new MemoryStream(zipBytes,true))
{
zipStream.Write(zipBytes, 0, zipBytes.Length);
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update))
{
//过滤要修改的文件
var fs = archive.Entries.Where((entry) => entry.Name.EndsWith("<customFilter>")).ToArray();
//foreach (var entry in fs)
for (int i = 0; i < fs.Length; i++)
{
var entry = fs[i];
string content;
using (StreamReader reader = new StreamReader(entry.Open()))
{
content = reader.ReadToEnd();
}
// 重新组合内容,根据自己的业务逻辑,重新拼接内容。
// 如果不是文本,需要根据对象组织byte数组
string newContent = "new";
string path = entry.FullName;
// 替换原文件内容
entry.Delete();
ZipArchiveEntry newEntry = archive.CreateEntry(path);
using (StreamWriter writer = new StreamWriter(newEntry.Open(), Encoding.UTF8))//注意数据的字符集
{
writer.Write(newContent);
}
}
}
File.WriteAllBytes(zipFilePath, zipStream.ToArray());
}
}
这里有两个个小点,需要注意。
- 由于是要对更改压缩流的内容,免不了要更新流已有的结构和长度。所以在创建内存流的时候,不能直接使用bytes[]来构造。
内存流在做容量计算时,只有私有成员_expandable为true时,才可以进行动态扩展,否则会报错。
_expandable默认为false,只有使用容量值初始化时,才会为true。所以采用了调用容量值构造,后进行写入bytes[]的方式,来加载流数据。System.NotSupportedException:“Memory stream is not expandable.” - 压缩流不能直接通过entry获取流然后复写。因为数据压缩后,长度及元数据都会有变化。所以采用了entry删除后,重新创建的方式进行更新。
浙公网安备 33010602011771号