o7planning

Compression and decompression in C#

  1. The class hierarchy
  2. ZipFile
  3. ZipArchive
  4. Appendix: Fix error

1. The class hierarchy

Here are the list of class using to compress or extract file. It is included in System.IO.Compression namespace
Class
Description
ZipFile
Provides static methods for creating, extracting, and opening zip archives.
ZipArchive
Represents a package of compressed files in the zip archive format.
ZipArchiveEntry
Represents a compressed file within a zip archive.
DeflateStream
Provides methods and properties for compressing and decompressing streams by using the Deflate algorithm.
GZipStream
Provides methods and properties used to compress and decompress streams.
Note that this class is introuduced in C# from version 4.5, therefore, your project must use .NET with 4.5 or newer version.

2. ZipFile

Zip File Class is an utility class, it has many static methods which help you to open the zip file, extract the data, or the situation is frequently used as compressing a directory into a zip file, extract the zip file to folder, ..
Simple example below uses the utility method of ZipFile class to compress a folder into a zip file and then extracting this file to a different folder.
ZipDirectoryDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Compression;

namespace CompressionTutorial
{
    class ZipDirectoryDemo
    {
        public static void Main(string[] args)
        {
            // The directory will be compressed.
            string inputDir = "C:/test/inputdir";

            // The output file after compressing the above directory.
            string zipPath = "C:/test/data.zip";

            // Extract the zip file to the folder.
            string extractPath = "C:/test/outputdir";

            // Create zip file by compressing a folder.
            ZipFile.CreateFromDirectory(inputDir, zipPath);

            // Extract the zip file to the folder.
            ZipFile.ExtractToDirectory(zipPath, extractPath);

            Console.WriteLine("Done!");
        }
    } 
}
If you get an error message: "The name 'ZipFile' does not exist in the current context" (Though you declared using System.IO.Compression) which means that your project using the older .NET 4.5 or the program does not find the DLL library. You can see how to fix this error in the appendix at the end of this document.
Run the example and get the results:
  • data.zip

3. ZipArchive

ZipArchive represents for a bundle of compressed files in a ZIP file format. You can retrieve the ZipArchive object through OpenRead method of ZipFile class . Through ZipArchive you can read the files which have been compressed in a zip file.
The example below lists the ZipArchiveEntry included in the zip file.
ListArchiveEntryDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Compression;
using System.IO; 

namespace CompressionTutorial
{
    class ListArchiveEntryDemo
    { 
        public static void Main(string[] args)
        {
            string zipPath =  "c:/test/data.zip";  
            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                // Fetch the list of ZipArchiveEntry(s).
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    Console.WriteLine("Entry:");
                    Console.WriteLine("  Name = " + entry.Name);
                    Console.WriteLine("  FullName = " + entry.FullName);
                }
            } 
            Console.Read();
        }
    } 
}
Running the example:
Entry:
  Name = data.docx
  FullName = data.docx
Entry:
  Name = image.bmp
  FullName = image.bmp
Entry:
  Name = readme.txt
  FullName = readme.txt
Entry:
  Name = Dotnet.docx
  FullName = documents\Dotnet.docx
Entry:
  Name = java.docx
  FullName = documents\java.docx
Extract data files in the zip file:
ExtractDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Compression;
using System.IO;

namespace CompressionTutorial
{
    class ExtractDemo {
        static void Main(string[] args)
        {
            string zipPath = "c:/test/data.zip"; 
            // Output Directory to unzip.
            string extractPath = "c:/test/extract";

            // if it doesn't exist, create
            if (!Directory.Exists(extractPath))
            {
                System.IO.Directory.CreateDirectory(extractPath);
            } 
            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    Console.WriteLine("Found: " + entry.FullName); 
                    // Find entries ends with .docx
                    if (entry.FullName.EndsWith(".docx", StringComparison.OrdinalIgnoreCase))
                    {
                        // ie: document/Dotnet.docx
                        Console.WriteLine(" - Extract entry: " + entry.FullName);

                        // C:/test/extract/documents/Dotnet.docx  ...
                        string entryOuputPath = Path.Combine(extractPath, entry.FullName); 
                        Console.WriteLine(" - Entry Ouput Path: " + entryOuputPath);

                        FileInfo fileInfo = new FileInfo(entryOuputPath); 
                        // Make sure the directory containing this file exists.
                        // ie: C:/test/extract/documents
                        fileInfo.Directory.Create();

                        // Overwrite old file if it already exists.
                        entry.ExtractToFile(entryOuputPath,true);
                    }
                }
            } 
            Console.ReadLine();
        }
    } 
}
Running the example:
Found: data.docx
 - Extract entry: data.docx
 - Entry Output Path: c:/test/extract\data.docx
Found: image.bmp
Found: readme.txt
Found: documents\Dotnet.docx
 - Extract entry: documents\Dotnet.docx
 - Entry Output Path: c:/test/extract\documents\Dotnet.docx
Found: documents\java.docx
 - Extract entry: documents\java.docx
 - Entry Output Path: c:/test/extract\documents\java.docx
You can also put the files into available zip file .
AddEntryDemo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Compression;
using System.IO;

namespace CompressionTutorial
{
    class AddEntryDemo
    {
        static void Main(string[] args)
        {
            string zipPath = "C:/test/data.zip";

            // Open stream to read zip file.
            using (FileStream zipStream = new FileStream(zipPath, FileMode.Open))
            {
                // Create ZipArchive object.
                using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update))
                {
                    // Add entry to ZipArchive.
                    ZipArchiveEntry readmeEntry = archive.CreateEntry("note/Note.txt");

                    // Create stream to write content to entry.
                    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                    {
                        writer.WriteLine("## Note.txt");
                        writer.WriteLine("========================");
                    }
                }
            }
        }
    } 
}
Run the example and get results.

4. Appendix: Fix error

If you get an error message: "The name 'ZipFile' does not exist in the current context" (Though you declared using System.IO.Compression) which means that your project using the older .NET 4.5 or the program does not find the DLL library.
Right-click the Project and select Properties, ensure that your project is using the .NET Framework 4.5 or higher.
If still errors
  • C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.IO.Compression.FileSystem.dll
  • C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1\System.IO.Compression.FileSystem.dll
Right-click the Project, Select:
  • Add/Reference..
Select file:
  • System.IO.Compression.FileSystem.dll
Similarly, if you get the notification as follows: "The name 'ZipArchive' does not exist in the current context", you need to declare using System.IO.Compression.dll library.
Similarly, if you get the notification as follows: "The name 'Path' does not exist in the current context", you need to declare using mscorlib.dll library.