更新压缩流

Posted on 2025-03-24 16:06  云起  阅读(16)  评论(0)    收藏  举报

最近遇到个新需求,要对压缩包内的数据进行更新。因为数据量不大,没有采用解压后重新打包的方式,直接采用了内存流进行处理。代码如下:

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());
	}
}

这里有两个个小点,需要注意。

  1. 由于是要对更改压缩流的内容,免不了要更新流已有的结构和长度。所以在创建内存流的时候,不能直接使用bytes[]来构造。
    内存流在做容量计算时,只有私有成员_expandable为true时,才可以进行动态扩展,否则会报错。
    System.NotSupportedException:“Memory stream is not expandable.”
    
    _expandable默认为false,只有使用容量值初始化时,才会为true。所以采用了调用容量值构造,后进行写入bytes[]的方式,来加载流数据。
  2. 压缩流不能直接通过entry获取流然后复写。因为数据压缩后,长度及元数据都会有变化。所以采用了entry删除后,重新创建的方式进行更新。

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3