wondra
wondra

Reputation: 3583

Overwrite contents of ZipArchiveEntry

How can I overwrite contents of a ZipArchiveEntry? Following code using StreamWriter with StringBuilder fails if the new file contents are shorter than the original ones, for example:

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"
   }
}

Produces file containing new and old contents mixed up "baz123123" instead of expected "baz123". Is there perhaps a way how to discard the old contents of ZipArchiveEntry before writing the new ones?
note: I do not want to extract the file, I would like to change contents of the archive.

Upvotes: 13

Views: 9231

Answers (3)

wondra
wondra

Reputation: 3583

An alternative is to SetLength(document.Length) of the entry.Open() stream.

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

Upvotes: 22

mjwills
mjwills

Reputation: 23975

The below code maintains your basic code structure, but explicitly deletes and recreates the file to ensure that 'leftover' data does not remain.

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

Upvotes: 12

Nkosi
Nkosi

Reputation: 247333

Updating the archive means you are either adding, moving or removing an entry from the archive.

Consider doing the following steps.

  • Get the entry content

  • Remove the entry from the archive (take note of name/location)

  • Modify content as desired.

  • Add modified content back to the archive.

Upvotes: 9

Related Questions