4

I have a large zip file (let's say 10 GB), to which I want to add a single small file (let's say 50 KB). I'm using the following code:

using System.IO.Compression;
using (var targetZip = ZipFile.Open(largeZipFilePath), ZipArchiveMode.Update)
{
    targetZip.CreateEntryFromFile(smallFilePath, "foobar");
}

While this works (eventually), it takes a very long time and consumes a ludicrous amount of memory. It seems to extract and recompress the whole archive.

How can I improve this in .Net 4.7? Solution without external dependencies is preferred, but not required if impossible.

3 Answers3

4

use visual studio nuget package manager and install that

Install-Package DotNetZip -Version 1.11.0

    using (ZipFile zip = new ZipFile())
  {
    zip.AddFile("ReadMe.txt"); // no password for this one
    zip.Password= "123456!";
    zip.AddFile("7440-N49th.png");
    zip.Password= "!Secret1";
    zip.AddFile("2005_Annual_Report.pdf");

    zip.Save("Backup.zip");
  }

https://www.nuget.org/packages/DotNetZip/

Onur Vatan
  • 111
  • 1
  • 5
4

Since you are in above .NET 4.5, you can use the ZipArchive (System.IO.Compression) class to achieve this. Here is the MSDN documentation: (MSDN).

Here is their example, it just writes text, but you could read in a .csv file and write it out to your new file. To just copy the file in, you would use CreateFileFromEntry, which is an extension method for ZipArchive.

using (FileStream zipToOpen = new FileStream(@"c:\users\exampleuser\release.zip", FileMode.Open))
{
   using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
   {
       ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
       using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
       {
           writer.WriteLine("Information about this package.");
           writer.WriteLine("========================");
       }
   }
}

Check this:- https://stackoverflow.com/a/22339337/9912441

https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-compress-and-extract-files

Ankur Tripathi
  • 471
  • 2
  • 16
  • ZipArchive.CreateEntryFromFile() is what I'm currently using. Using this code on a 10 GB zip archive takes about 5 min and 10 GB memory, which is exactly what I want to avoid. – Jonathan ARWECK Aug 29 '18 at 13:16
0

I found the reason for this behaviour in another Stack Overflow answer: Out of memory exception while updating zip in c#.net.

The gist of it is that this takes a long time because ZipArchiveMode.Update caches the zip file into memory. The suggestion for avoiding this caching behaviour is to create a new archive, and copy the old archive contents along with the new file to it.

See the MSDN documentation which explains how ZipArchiveMode.Update behaves:

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Progeny42
  • 43
  • 5