Reading and writing Zip files

Other topics

Remarks:

  • You can also use a MemoryStream instead of a FileStream.

  • Exceptions

ExceptionCondition
ArgumentExceptionThe stream has already been closed, or the capabilities of the stream does not match the mode (eg: trying to write to a read only stream)
ArgumentNullExceptioninput stream is null
ArgumentOutOfRangeExceptionmode has an invalid value
InvalidDataExceptionSee list below

When a InvalidDataException is thrown, it can have 3 causes:

  • The contents of the stream could not be interpreted as a zip archive
  • mode is Update and an entry is missing from the archive or is corrupt and cannot be read
  • mode is Update and an entry is too large to fit into memory

All information has been taken from this MSDN page

Listing ZIP contents

This snippet will list all the filenames of a zip archive. The filenames are relative to the zip root.

using (FileStream fs = new FileStream("archive.zip", FileMode.Open))
using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Read))
{
    for (int i = 0; i < archive.Entries.Count; i++)
    {
        Console.WriteLine($"{i}: {archive.Entries[i]}");
    }
}

Extracting files from ZIP files

Extracting all the files into a directory is very easy:

using (FileStream fs = new FileStream("archive.zip", FileMode.Open))
using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Read))
{
    archive.ExtractToDirectory(AppDomain.CurrentDomain.BaseDirectory);
}

When the file already exists, a System.IO.IOException will be thrown.

Extracting specific files:

using (FileStream fs = new FileStream("archive.zip", FileMode.Open))
using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Read))
{
    // Get a root entry file
    archive.GetEntry("test.txt").ExtractToFile("test_extracted_getentries.txt", true);

    // Enter a path if you want to extract files from a subdirectory
    archive.GetEntry("sub/subtest.txt").ExtractToFile("test_sub.txt", true);

    // You can also use the Entries property to find files
    archive.Entries.FirstOrDefault(f => f.Name == "test.txt")?.ExtractToFile("test_extracted_linq.txt", true);

    // This will throw a System.ArgumentNullException because the file cannot be found
    archive.GetEntry("nonexistingfile.txt").ExtractToFile("fail.txt", true);
}

Any of these methods will produce the same result.

Updating a ZIP file

To update a ZIP file, the file has to be opened with ZipArchiveMode.Update instead.

using (FileStream fs = new FileStream("archive.zip", FileMode.Open))
using (ZipArchive archive = new ZipArchive(fs, ZipArchiveMode.Update))
{
    // Add file to root
    archive.CreateEntryFromFile("test.txt", "test.txt");

    // Add file to subfolder
    archive.CreateEntryFromFile("test.txt", "symbols/test.txt");
}

There is also the option to write directly to a file within the archive:

var entry = archive.CreateEntry("createentry.txt");
using(var writer = new StreamWriter(entry.Open()))
{
    writer.WriteLine("Test line");
}

Contributors

Topic Id: 9943

Example Ids: 30569,30570,30571

This site is not affiliated with any of the contributors.