覆盖ZipArchiveEntry的内容

won*_*dra 3 c# zip streamwriter

我怎样才能覆盖一个内容ZipArchiveEntry?使用下面的代码StreamWriter使用StringBuilder,如果新的文件内容比原来的短,例如失败:

using System.IO.Compression;
//...
using (var archive = ZipFile.Open("Test.zip", ZipArchiveMode.Update))
{
   StringBuilder document;
   var entry = archive.GetEntry("foo.txt");//entry contents "foobar123"
   using (StreamReader reader = new StreamReader(entry.Open()))
   {
      document = new StringBuilder(reader.ReadToEnd());
   }

   document.Replace("foobar", "baz"); //builder contents "baz123"

   using (StreamWriter writer = new StreamWriter(entry.Open()))
   {
      writer.Write(document); //entry contents "baz123123", expected "baz123"
   }
}
Run Code Online (Sandbox Code Playgroud)

生成包含新旧内容的文件混合"baz123123"而不是预期的"baz123".ZipArchiveEntry在编写新内容之前,是否有一种方法可以丢弃旧内容?
注意:我不想解压缩文件,我想更改存档的内容.

won*_*dra 9

另一种方法是SetLength(document.Length)所述的entry.Open()流.

using(var stream = entry.Open())
{
   stream.SetLength(document.Length);
   using (StreamWriter writer = new StreamWriter(stream))
   {
      writer.Write(document); //entry contents "baz123"
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案!`SetLength(0)`在最终长度未知的情况下也适用于我. (3认同)
  • 啊。我刚刚注意到 Paul B 的评论。这个解决方案也有效,而且说实话,我对此感到更舒服。现在我知道流正在扩展以容纳实际数据。 (2认同)

Nko*_*osi 7

更新档案意味着您要从档案中添加、移动或删除条目。

考虑执行以下步骤。

  • 获取入口内容

  • 从存档中删除条目(记下名称/位置)

  • 根据需要修改内容。

  • 将修改后的内容添加回存档。

  • 刚刚发现设置 `entry.Open()` 流的 `SetLength(document.Length)` 也有效。如果 API 与 `Stream` 一致,那么使用 `bool append` 的重载仍然会受到欢迎。 (2认同)

mjw*_*lls 5

下面的代码维护您的基本代码结构,但显式删除并重新创建该文件以确保不保留“剩余”数据。

using (var archive = ZipFile.Open("Test.zip", ZipArchiveMode.Update))
{
    StringBuilder document;
    var entry = archive.GetEntry("foo.txt");//entry contents "foobar123"
    using (StreamReader reader = new StreamReader(entry.Open()))
    {
       document = new StringBuilder(reader.ReadToEnd());
    }

    entry.Delete();
    entry = archive.CreateEntry("foo.txt");
    document.Replace("foobar", "baz"); //builder contents "baz123"

    using (StreamWriter writer = new StreamWriter(entry.Open()))
    {
       writer.Write(document);
    }
}
Run Code Online (Sandbox Code Playgroud)