gpt4 book ai didi

c# - 更新 ZipArchive 中的文件

转载 作者:太空宇宙 更新时间:2023-11-03 22:38:31 24 4
gpt4 key购买 nike

我有一个 ZipArchive 对象,它包含一个我正在修改的 XML 文件。然后我想返回修改后的 ZipArchive。

这是我的代码:

var package = File.ReadAllBytes(/* location of existing .zip */);

using (var packageStream = new MemoryStream(package, true))
using (var zipPackage = new ZipArchive(packageStream, ZipArchiveMode.Update))
{
// obtain the specific entry
var myEntry = zipPackage.Entries.FirstOrDefault(entry => /* code elided */));

XElement xContents;
using (var reader = new StreamReader(myEntry.Open()))
{
// read the contents of the myEntry XML file
// then modify the contents into xContents
}

using (var writer = new StreamWriter(myEntry.Open()))
{
writer.Write(xContents.ToString());
}

return packageStream.ToArray();
}

此代码在 packageStream.ToArray() 调用中抛出“内存流不可扩展”异常。

谁能解释我做错了什么,更新 ZipArchive 中现有文件的正确方法是什么?

最佳答案

显然,ZipArchive 想要扩展或调整 ZIP 存档流的大小。但是,您提供了一个具有固定流长度的MemoryStream(由于使用构造函数MemoryStream(byte[], bool),它创建一个固定长度的内存流,该长度等于提供给构造函数的数组的长度)。

因为 ZipArchive 想要扩展(或调整大小)流,提供一个可调整大小的 MemoryStream(使用它的无参数构造函数)。然后将原始文件数据复制到此 MemoryStream 并继续进行 ZIP 存档操作。

并且不要忘记在将原始文件数据复制到其中后将MemoryStream 读/写位置重置回0,否则ZipArchive 尝试从此流中读取 ZIP 存档数据时只会看到“流结束”。

using (var packageStream = new MemoryStream())
{
using (var fs = File.OpenRead(/* location of existing .zip */))
{
fs.CopyTo(packageStream);
}

packageStream.Position = 0;


using (var zipPackage = new ZipArchive(packageStream, ZipArchiveMode.Update))
{
... do your thing ...
}


return packageStream.ToArray();
}

这里的代码包含一个更正。在问题的原始代码中,return packageStream.ToArray(); 已被放置在ZipArchive< 的using block 中/em>。在执行该行时,ZipArchive 实例可能尚未将所有数据写入 MemoryStream,可能会将某些数据保留在某些内部缓冲区中和/或可能推迟编写一些 ZIP 数据结构。

为了确保 ZipArchive 实际上已经将所有必要的数据完全写入 MemoryStream,这里只需移动 return packageStream.ToArray();ZipArchive using block 之后。在其 using block 的末尾,ZipArchive 将被释放,这也将确保 ZipArchive 已将所有尚未写入的数据写入流。因此,在处理掉 ZipArchive 之后访问 MemoryStream 将产生完全更新的 ZIP 存档的完整数据。


旁注:仅对较小的 ZIP 文件执行此操作。 MemoryStream 显然会使用内部数据缓冲区(数组)来保存 MemoryStream 中的数据。但是,packageStream.ToArray();会在MemoryStream中创建一份数据副本,所以一段时间内这个例程的内存需求会多一点超过 ZIP 存档大小的两倍。

关于c# - 更新 ZipArchive 中的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53695197/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com