Zip(Archive) API’s in .NET Framework 4.5 – ZipArchive Class

With release of .NET Framework 4.5, Microsoft has introduced new classes in to System.IO.Compression namespace. These classes will add the necessary programming support for Zipping(Achiving), and Extracting support for Zip Files in your .NET Source Code.

Below are the newly introduced classes as part of .NET Framework 4.5:

ZipArchive – Represents a package of compressed files in the zip archive format.

ZipArchiveEntry – Represents a compressed file within a zip archive.

ZipFile – Provides static methods for creating, extracting, and opening zip archives.

ZipFileExtensions – Provides extension methods for the ZipArchive and ZipArchiveEntry classes.

In this blog post I am going to discuss about ZipArchive class which will help you with most of the important tasks in Archiving a file or folder using .NET.

The ZipArchive class enables you to work with a package of compressed files. The package contains an entry for each compressed file. You can:

  • Retrieve an entry by using the GetEntry method.
  • Retrieve the entire collection of entries by using the Entries property.
  • Create a new entry in the package by calling the overloaded CreateEntry method.

If you add reference for the System.IO.Compression.FileSystem assembly in your project, you can access three extension methods (from the ZipFileExtensions class) for the ZipArchive class: CreateEntryFromFile, CreateEntryFromFile, and ExtractToDirectory. These extension methods enable you to compress and decompress the contents of the entry to a file.

The System.IO.Compression.FileSystem assembly is not available for Windows Store apps.

In Windows Store apps, you can compress and decompress files by using the DeflateStream or GZipStream class, or you can use the Windows Runtime types Compressor and Decompressor.

Here is the quick sample that would help you to understand how to use ZipArchive class. Code is self explanatory – hope that helps. There are three methods ZipFiles – zip all files in a folder, ExtractFile – to extract files with specificname, ExtractFiles – extract multiple files.

Please go through the below code snippet. If you need additional information: visit MSDN Ref on System.IO.Compression, and in later posts we might discuss about the ZipFile class in more detail.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO.Compression;
using System.IO;

namespace ConsoleApp01
{
    class Program
    {
        static void Main(string[] args)
        {
            string targetZip = AppDomain.CurrentDomain.BaseDirectory + "\" + System.Guid.NewGuid().ToString() + ".zip";

            string sourceFolder = AppDomain.CurrentDomain.BaseDirectory + "\Sample01" ; //We are going to zip the whole contents of the folder. 

            Console.WriteLine(String.Format("Now Archiving the folder/file {0}, to target zip:{1} ", sourceFolder, targetZip));

            //Zipping the folder 
            ZipFiles(sourceFolder, targetZip);



            string extractFolder = AppDomain.CurrentDomain.BaseDirectory + "\" + Path.GetFileNameWithoutExtension(targetZip);

            Console.WriteLine(String.Format("Now Extracting the file {0}, to location:{1} ", targetZip, extractFolder));

            //Extract the entire Zip file 
            ExtractFiles(targetZip, extractFolder);



            //Extract files based on search pattern such as *.txt
            string extractFolder2 = AppDomain.CurrentDomain.BaseDirectory + "\" + Path.GetFileNameWithoutExtension(targetZip) + "12";

            Console.WriteLine(String.Format("Now Extracting the selected file(s) {0}, to location:{1} ", targetZip, extractFolder2));
            
            //Extract the entire Zip file 
            ExtractFiles(targetZip, extractFolder2, "*.txt");

            Console.WriteLine("Press any key to exit");

            Console.ReadKey();
        }

        /// <summary>
        /// Zips the files from the source folder - for now single level - assuming that we will be zipping all the files in a folder. 
        /// not the child folders and files in it, we will ignore it.
        /// </summary>
        /// <param name="sourceFilesFolderPath">The source files folder path.</param>
        /// <param name="targetZipFilePath">The target zip file path.</param>
        /// <param name="searchPattern">The search pattern.</param>
        public static void ZipFiles(string sourceFilesFolderPath, string targetZipFilePath, string searchPattern = "")
        {
            //if Source Directory exists. 
            if (Directory.Exists(sourceFilesFolderPath))
            {
                using (FileStream zipToOpen = new FileStream(targetZipFilePath, FileMode.OpenOrCreate))
                {
                    //Open Archieve for update
                    using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                    {
                        //Getting directory info
                        DirectoryInfo dInfo = new DirectoryInfo(sourceFilesFolderPath);


                        //Getting all files list in the folder 
                        FileInfo[] filesList = dInfo.GetFiles(searchPattern);

                        if (String.IsNullOrEmpty(searchPattern)) //fail safe to retrieve all
                            filesList = dInfo.GetFiles();

                        if (filesList != null && filesList.Length > 0)
                        {
                            //Creating archieve entry for each file in the folder 
                            foreach (FileInfo file in filesList)
                            {
                                archive.CreateEntryFromFile(file.FullName, file.Name);
                            }
                        }


                    }

                }
            }
            else
            {
                throw new DirectoryNotFoundException(String.Format("Source folder: {0} not found",sourceFilesFolderPath);
            }

        }




        /// <summary>
        /// Extracts the files.
        /// </summary>
        /// <param name="sourceZipPath">The source zip path.</param>
        /// <param name="targetExtractPath">The target extract path.</param>
        /// <param name="conditionalExtractPattern">The conditional extract pattern.(OPTIONAL)</param>
        public static void ExtractFiles(string sourceZipPath, string targetExtractPath, string conditionalExtractPattern = "")
        {
            string zipPath      = sourceZipPath;  //Source Zip File 
            string extractPath  = targetExtractPath; //Path to Extract

            if (!Directory.Exists(targetExtractPath))
            {
                Directory.CreateDirectory(targetExtractPath);
            }

            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {

                //STEP 1
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    //Conditional extract
                    if (!String.IsNullOrEmpty(conditionalExtractPattern))
                    {
                        if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
                        {
                            entry.ExtractToFile(Path.Combine(extractPath, entry.FullName),true);
                        }
                    }
                    else // extract all..
                    {
                        entry.ExtractToFile(Path.Combine(extractPath, entry.FullName),true);
                    }

                    
                }

                //Or EXTRACT ALL USING 

                //STEP 2
                //archive.ExtractToDirectory(targetExtractPath);

            } 

        }




        /// <summary>
        /// Extracts the file.
        /// </summary>
        /// <param name="sourceZipPath">The source zip path.</param>
        /// <param name="targetExtractPath">The target extract path.</param>
        /// <param name="extractFileName">Name of the extract file.</param>
        public static void ExtractFile(string sourceZipPath, string targetExtractPath, string extractFileName)
        {
            string zipPath = sourceZipPath;  //Source Zip File 
            string extractPath = targetExtractPath; //Path to Extract

            using (ZipArchive archive = ZipFile.OpenRead(zipPath))
            {
                //STEP 1
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    //Conditional extract
                    if (!String.IsNullOrEmpty(extractFileName))
                    {
                        //Extract the file.
                        if (entry.FullName.EndsWith(extractFileName, StringComparison.OrdinalIgnoreCase))
                        {
                            entry.ExtractToFile(Path.Combine(extractPath, entry.FullName), true);
                        }
                    }

                }

            }

        }

    
    }
}