【问题标题】:Edit ZipArchive in memory .NET在内存 .NET 中编辑 ZipArchive
【发布时间】:2016-03-31 13:42:21
【问题描述】:

我正在尝试编辑包含在 Zip 文件中的 XmlDocument 文件:

var zip = new ZipArchive(myZipFileInMemoryStream, ZipArchiveMode.Update);
var entry = zip.GetEntry("filenameToEdit");
using (var st = entry.Open())
{
    var xml = new XmlDocument();
    xml.Load(st);
    foreach (XmlElement el in xml.GetElementsByTagName("Relationship"))
    {
        if(el.HasAttribute("Target") && el.GetAttribute("Target").Contains(".dat")){
            el.SetAttribute("Target", path);
        }
    }
    xml.Save(st);
}

执行此代码后,包含的文件不会更改。如果我将 xml 写入磁盘而不是 xml.Save(st);,我得到了已编辑的。

为什么编辑后的文件没有写入 zip?我该如何解决?

编辑:

我更新了代码:

var tmp = new MemoryStream();
using (var zip = new ZipArchive(template, ZipArchiveMode.Read, true))
{
    var entry = zip.GetEntry("xml");
    using (var st = entry.Open())
    {
        var xml = new XmlDocument();
        xml.Load(st);
        foreach (XmlElement el in xml.GetElementsByTagName("Relationship"))
        {
            if (el.HasAttribute("Target") && el.GetAttribute("Target").Contains(".dat"))
            {
                el.SetAttribute("Target", path);
            }
        }
        xml.Save(tmp);
    }
}
using (var zip = new ZipArchive(template, ZipArchiveMode.Update, true))
{
    var entry = zip.GetEntry("xml");
    using (var st = entry.Open())
    {
        tmp.Position = 0;
        tmp.CopyTo(st);
    }
}

以这种方式编辑 zip 文件,但它仅在流的长度相等时才有效。如果tmp 更短,则st 的其余部分仍在文件中...

提示?

【问题讨论】:

  • 我没有看到你在任何地方保存 zip :)
  • 我跳过了将myZipFileInMemoryStream 保存到磁盘的部分。编辑的部分不应该包含在流中吗?
  • 显然,它应该 - After retrieving the stream, you can read from or write to the stream. When you write to the stream, the modifications you make to the entry will appear in the zip archive. (MSDN)。但是您还必须回退流 - st.Position = 0,否则您只是将新 XML 添加到旧 XML 的末尾。这可能是问题吗? :)
  • 添加st.Position = 0; 会引发错误This operation is not supported
  • 嗯,ZIP 并不真正支持完整的就地更新。最好的解决方案可能只是删除文件并重新创建。

标签: c# edit xmldocument ziparchive


【解决方案1】:

我使用此代码创建一个 Zip InMemory(使用 DotNetZip 库):

        MemoryStream saveStream = new MemoryStream();

        ZipFile arrangeZipFile = new ZipFile();
        arrangeZipFile.AddEntry("test.xml", "content...");
        arrangeZipFile.Save(saveStream);

        saveStream.Seek(0, SeekOrigin.Begin);
        saveStream.Flush(); // might be useless, because it's in memory...

之后,我在 MemoryStream 中有一个有效的 Zip。我不确定为什么要添加 Flush() - 我猜这是多余的。

要编辑现有的 Zip,您可以在 MemoryStream 中读取它,而不是使用“new ZipFile(byteArray...)”来创建“new ZipFile()”。

【讨论】:

  • 即使test.xml 已经存在,它还能工作吗?如果我想将文件放在子文件夹中怎么办? content 是干什么用的?
  • arrangeZipFile.AddEntry("test.xml", "content..."); => 将在 zip 中创建一个新的“text.xml”文件,该文件存储在内存中,具有给定的内容。如果要更新条目,只需使用 UpdateEntry 方法。对于子文件夹:至少 DotNetZip 将只使用给定的路径,例如如果你想创建一个子文件夹,只需这样命名:AddEntry("subfolder/test.xml"..)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 2013-02-14
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-21
  • 1970-01-01
相关资源
最近更新 更多