Compression and decompression in C#

1- Introduction

History:
  • Create document: 04-12-2015

2- The class hierarchy compression and decompression

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.

3- 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";

            // output file, folder compression on.
            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

4- 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))
           {
      
               foreach (ZipArchiveEntry entry in archive.Entries)
               {
                   Console.WriteLine("Entry:");
                   Console.WriteLine("  Name = " + entry.Name);
                   Console.WriteLine("  FullName = " + entry.FullName);
               }
           }

           Console.Read();
       }
   }

}
Running the example:
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";

            // Directory to unzip to
            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);

                        // ie: 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 the 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:
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";

           // Mở một luồng đọc file zip.
           using (FileStream zipStream = new FileStream(zipPath, FileMode.Open))
           {
               // Tạo đối tượng ZipArchive.
               using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update))
               {
                   // Thêm một entry vào ZipArchive.
                   ZipArchiveEntry readmeEntry = archive.CreateEntry("note/Note.txt");

                   // Tạo một luồng ghi nội dung vào entry.
                   using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                   {
                       writer.WriteLine("## Note.txt");
                       writer.WriteLine("========================");
                   }
               }
           }
       }
   }

}
Run the example and get results.

5- TODO

  • TODO 50%

6- Appendix: Fix error The name 'xxx' does not exist in the current context

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.