More .NET components

Advanced ZIP features

ZIP archive opening modes #

When initializing ZipArchive from a file, use ArchiveOpenMode and ArchiveAccessMode parameters to specify how to open or create the ZIP file:

CSharp

// open existing ZIP archive in read-only mode
var zip = new ZipArchive(
    @"C:\MyData\archive.zip",
    ArchiveOpenMode.Open,
    ArchiveAccessMode.Read);

When using a ZipArchive initalized from a stream, closing the ZipArchive will close the underlying stream as well be default. To change this behavior, specify ArchiveStreamCloseMode.LeaveOpen.

CSharp

// do not close the stream when ZipArchive is closed
var zip = new ZipArchive(stream, ArchiveStreamCloseMode.LeaveOpen);

Setting comments #

To get or set a ZIP archive comment, use the ZipArchive.Comment property. To get or set a comment of an item (such as a file) in the ZIP archive, use the ZipItem.Comment property.

CSharp

// add comment to the ZIP archive
zip.Comment = "This archive contains financial data for the year 2000.";

// add comment to a particular file
zip["orders-2000-01.txt"].Comment = "This file contains list of orders from January 2000.";

Note: The maximum length of a comment is limited to 65,535 bytes. ZipItem comments are encoded using UTF-8 character set. ZipArchive comments are encoded using IBM Code Page 437 character set.

Setting compression level #

To set compression level, use ZipArchive.CompressionLevel property. It accepts values from 0 to 9, where 0 means no compression (fastest) and 9 means best compression (slowest). The default compression level is 6 (medium compression and speed).

CSharp

// specify best (and slowest) compression (default is 6)
zip.CompressionLevel = 9;

Note: CompressionLevel only applies to newly added files.

Setting compression method #

To specify compression method, use ZipArchive.CompressionMethod property.

CSharp

// specify enhanced deflate - compatible with Deflate64(tm) by PKWARE, Inc.
zip.CompressionMethod = CompressionMethod.EnhancedDeflate;

Note: CompressionMethod only applies to newly added files.

Protecting ZIP archives with password #

To protect archived data from being extracted by unauthorised users, use ZipArchive.Password property.

WinZip® AE-2 encryption algorithm is used by default. To specify a different encryption algorithm, use ZipArchive.EncryptionAlgorithm property.

CSharp

// set password first
zip.Password = "SecretPassword";

// specify encryption algorithm (default is AES-256)
zip.EncryptionAlgorithm = EncryptionAlgorithm.Aes128;

// add some files (they will be encrypted)
zip.Add(@"C:\MyData\private\*.*");

// disable encryption for subsequently-added files
zip.Password = null;

// or set encryption to none
zip.EncryptionAlgorithm = EncryptionAlgorithm.None;

// add some files (they will not be encrypted)
zip.Add(@"C:\MyData\public\*.*");

Note: encryption only applies to newly added files.

Note: We are unable to support the proprietary and patented SES encryption format because its vendor refused to grant us a license. Fortunately, due to licensing issues, most third-party ZIP applications and libraries use WinZip® AE-2 instead.

Note: The ZIP format makes it possible to set a different password for each file. However, this is discouraged because it could confuse users and third-party ZIP applications.

Warning: For compatibility with legacy ZIP archives, we also support traditional PKWARE's ZIP 2.0 encryption (EncryptionAlgorithm.Zip20). However, please be aware that this algorithm is considered very weak and should no longer be used.

WinZip is a registered trademark of Corel Corporation.

Encrypting existing ZIP archives #

If you already have a ZIP archive and need to encrypt it with a password, use ZipArchive.Encrypt method. This will encrypt the compressed archive files without the need to recompress them.

CSharp

// encrypt 'archive.zip' using AES-256 encryption algorithm
ZipArchive.Encrypt(
    @"C:\MyData\archive.zip",
    @"C:\MyData\encrypted-archive.zip",
    "SecretPassword",
    EncryptionAlgorithm.Aes256);

Tip: For a reverse process, use ZipArchive.Decrypt method.

Extracting encrypted ZIP archives #

To extract contents of a protected ZIP archive, set ZipArchive.Password property:

CSharp

// set the password before extracting
zip.Password = "SecretPassword";

// extract all files
zip.ExtractAll(@"C:\MyData\Out");

Alternatively, do this in a custom PasswordRequired event:

CSharp

// register PasswordRequired event to handle password requests
zip.PasswordRequired += (s, e) =>
{
    if (e.Reason == ArchivePasswordReason.IncorrectPasswordOrCorruptedData)
    {
        Console.WriteLine(
            "The password for '{0}' is incorrect.",
            e.ArchiveItemPath);
    }

    // ask user for a password
    Console.WriteLine("Password: ");
    string password = GetPasswordFromUser();

    // set the password
    e.Password = password;

    // or set default ZipArchive password to keep using it for subsequent files
    zip.Password = password;
};

// extract all files
// (PasswordRequired event will be raised if password is required)
zip.ExtractAll(@"C:\MyData\Out");

Multithreading support #

ZipArchive class can utilize multiple threads to improve compression performance. By default, the number of compressor threads depends on the number of CPU cores and ThreadPool settings. however, this can be changed using ZipArchive.Options.CompressorCount property.

CSharp

// disable multithreaded compression
zip.Options.CompressorCount = 1;

// specify preferred number of compressor threads
zip.Options.CompressorCount = 4;

Tip: Using more than 4 threads is unlikely to result in any significantly performance enhancement.

Note: Multithreaded compression is not supported on .NET Compact Framework.

Archive shrinking #

If the ZIP file contains gaps, calling ZipArchive.Save(ArchiveSaveAction.Shrink) method will shrink it and remove the gaps.

This is usually needed after deleting files from a ZIP archive in delayed mode:

CSharp

// register ShrinkProgress event
zip.ShrinkProgress += (s, e) =>
{
    Console.WriteLine("Shrinking: {0}/{1} {2}%", e.ItemsProcessed, e.ItemsTotal, e.ProgressPercentage);
};

// get info of ZIP file (for demo purposes only)
var info = new FileInfo(zip.FilePath);

// print current ZIP file size
Console.WriteLine("Before delete: {0} bytes", info.Length);

// disable immediate save to prevent from automatic shrinking
zip.SaveMode = ArchiveSaveMode.Delayed;

// delete some files (resulting in unused gaps inside the ZIP file)
zip.DeleteFile("file1.txt");
zip.DeleteFile("file4.txt");
zip.DeleteFile("file6.txt");

// print current ZIP file size
Console.WriteLine("After delete: {0} bytes", new FileInfo(zip.FilePath).Length);

// shrink archive to decrease size of final ZIP file
zip.Save(ArchiveSaveAction.Shrink);

// print current ZIP file size
Console.WriteLine("After shrink: {0} bytes", new FileInfo(zip.FilePath).Length);

Large file support (ZIP64™) #

The original ZIP format has very low size limits (see table below). However, Rebex ZIP supports the new ZIP64™ format as well, making it possible to surpass these limitations.

Original ZIP ZIP64™
Total size of ZIP archive in bytes 232 - 1 (4 GB) 264 - 1 (16 EB)
Uncompressed size of a file in archive 232 - 1 (4 GB) 264 - 1 (16 EB)
Total number of entries in archive 216 - 1 (65535) 232 - 1 (4 billion)

Note: ZIP64™ format is not used by default to maintain wide compatibility. However, it is used automatically when needed. To change this behavior, use ZipArchive.Options.Zip64Mode property:

CSharp

// disable ZIP64(tm) format
zip.Options.Zip64Mode = Zip64Mode.Never;

Note: In practice, the maximum file size might be limited by the underlying file system. Check out File systems limits.

Note: Please note that some ZIP tools don't support ZIP64™ format, which can lead to inability to extract ZIP64™ archives (even if smaller than 4 GB).

The ZIP64™ is a registered trademark of PKWARE, Inc.

Enhanced deflate (Deflate64™) #

The DEFLATE compression algorithm uses 32 KB sliding window, while Enhanced Deflate uses 64 KB sliding window and allows longer lengths for repetitive segments. Enhance Deflate can lead to big improvements in compression ratios for highly-compressable files.

CSharp

// specify Enhanced Deflate - compatible with Deflate64(tm) by PKWARE
zip.CompressionMethod = CompressionMethod.EnhancedDeflate;

Note: Please note that some ZIP tools don't support Deflate64™ format.

Deflate64™ is a registered trademark of PKWARE, Inc.

Delayed mode #

The ZipArchive object works in auto-save mode by default, which means that changes made to the ZIP archive are saved to the underlying stream immediately.

This makes the ZipArchive object easy to use and ensures that the ZIP archive is complete and readable between subsequent actions. However, this approach can cause noticeable slow-down when performing a lot of certain operations. For example, when adding or deleting 100 files on-by-one (or just updating their comments), the updated ZIP archive central-directory-structure would have to be saved during each of those calls, again and again.

To avoid this, set the ZipArchive.SaveMode property to ArchiveSaveMode.Delayed, perform desired operations and explicitly call the Save() method to commit all changes once.

CSharp

// turn off 'auto-save' mode
zip.SaveMode = ArchiveSaveMode.Delayed;

// add files in the 'C:\MyData' directory one-by-one
string[] files = Directory.GetFiles(@"C:\MyData");
foreach (string file in files)
{
    zip.AddFile(file);
}

// save all changes made earlier
// (this has to be done before turning on 'auto-save' mode again)
zip.Save();

// turn on 'auto-save' mode again
zip.SaveMode = ArchiveSaveMode.Immediate;

Note: Deleting files in auto-save mode also causes the ZIP file to be shrinked (to remove the gap in the ZIP archive). when performing many delete operations, switching to delayed mode (even temporarily) might result in substantial speed boost.

Deflate, ZLIB and GZIP streams #

Rebex ZIP also features CompressionStream and DecompressionStream classes for working with raw compression/decompression streams using DEFLATE, ZLIB or GZIP formats.

CSharp

// set compression format according to user selection
CompressionFormat format;
switch (userSelection)
{
    case "deflate":
        format = CompressionFormat.Deflate;
        break;
    case "zlib":
        format = CompressionFormat.Zlib;
        break;
    case "gzip":
        format = CompressionFormat.Gzip;
        break;
    default:
        throw new InvalidOperationException("Invalid compression format.");
}

// prepare output file name
string filePath = @"C:\MyData\output." + userSelection;

// open stream for writing compressed data
using (var output = new CompressionStream(File.Create(filePath), OpenMode.Write, format, CompressionMethod.Deflate))
{
    using (var writer = new StreamWriter(output))
    {
        writer.WriteLine("Sample text.");
    }
}

// open stream for reading decompressed data
using (var input = new DecompressionStream(File.OpenRead(filePath), OpenMode.Read, format, CompressionMethod.Deflate))
{
    using (var reader = new StreamReader(input))
    {
        string data = reader.ReadToEnd();
        Console.WriteLine(data);
    }
}

Note: For GZIP format, Rebex ZIP also provides GzipCompressionStream and GzipDecompressionStream classes with additional GZIP-specific features.