合并两个内存Zip流时出现ObjectDisposedException异常的求助
问题根因
- 触发
ObjectDisposedException的直接原因:ZipStorer.Close()执行时会默认关闭你传入的底层MemoryStream,你的GetText/GetTwoText方法在storer.Close()之后才返回流,此时返回的流已经处于被释放状态,后续访问Length/Position属性时自然抛出异常。 - 存在严重逻辑错误:直接拼接两个ZIP文件的字节流无法得到合法的合并归档,ZIP格式有固定的文件头、中央目录结构,简单拼接后的文件无法被识别为正常压缩包。
解决方案
第一步:修正Get系列方法,避免返回已释放的流
调整方法逻辑,将生成的ZIP字节单独封装为新的MemoryStream返回,不受ZipStorer释放逻辑影响:
public static Task<Stream> GetText() { MemoryStream tempStream = new MemoryStream(); using (ZipStorer storer = ZipStorer.Create(tempStream, "")) { byte[] byteArray = Encoding.ASCII.GetBytes("This is my Text"); using MemoryStream entryStream = new MemoryStream(byteArray); storer.AddStream(ZipStorer.Compression.Deflate, "example.txt", entryStream, DateTime.Now, null); } // 用生成好的字节数组新建独立的MemoryStream返回,不会被外部释放逻辑影响 var zipBytes = tempStream.ToArray(); return Task.FromResult<Stream>(new MemoryStream(zipBytes)); } // GetTwoText方法做相同修改即可 public static Task<Stream> GetTwoText() { MemoryStream tempStream = new MemoryStream(); using (ZipStorer storer = ZipStorer.Create(tempStream, "")) { byte[] byteArray = Encoding.ASCII.GetBytes("TWOWOWOWOWOWO"); using MemoryStream entryStream = new MemoryStream(byteArray); storer.AddStream(ZipStorer.Compression.Deflate, "exampleTWO.txt", entryStream, DateTime.Now, null); } var zipBytes = tempStream.ToArray(); return Task.FromResult<Stream>(new MemoryStream(zipBytes)); }
第二步:正确合并两个ZIP归档
不要直接拼接流,而是新建一个目标ZIP归档,读取两个输入ZIP的所有条目写入新归档:
class Program { static async Task Main() { // 并发获取两个ZIP流 var zipTasks = new List<Task<Stream>> { GetText(), GetTwoText() }; await Task.WhenAll(zipTasks); var inputZips = zipTasks.Select(t => t.Result).ToList(); using var outputStream = new MemoryStream(); using var outputZip = ZipStorer.Create(outputStream, ""); // 遍历所有输入ZIP,把条目全部拷贝到输出ZIP foreach (var zipStream in inputZips) { zipStream.Position = 0; using var inputZip = ZipStorer.Open(zipStream, FileAccess.Read); var allEntries = inputZip.ReadCentralDir(); foreach (var entry in allEntries) { using var entryContent = new MemoryStream(); inputZip.ExtractFile(entry, entryContent); entryContent.Position = 0; outputZip.AddStream(ZipStorer.Compression.Deflate, entry.FilenameInZip, entryContent, entry.ModifyTime, null); } } outputZip.Close(); File.WriteAllBytes("ghbrj.zip", outputStream.ToArray()); // 释放输入流资源 foreach (var stream in inputZips) { stream.Dispose(); } } }
你之前写的Append扩展方法和Aggregate拼接逻辑完全不符合ZIP格式要求,可以直接删除。
内容的提问来源于stack exchange,提问作者jan
相关产品推荐
相关产品推荐

