Сжатие и декомпрессия в C#

1- Иерархия классов

Ниже приведен список классов, используемых для сжатия или извлечения файла. Они находятся в пространстве имен System.IO.Compression
Class Description
ZipFile Предоставляет статические методы для создания, извлечения данных и открытия файлов данных архивов zip.
ZipArchive Представляет файлы сжатые в одном файле формата ZIP.
ZipArchiveEntry Представляет папки сжатые в одном архиве формата ZIP.
DeflateStream Предоставляет методы и свойства для сжатых и извлеченных потоков (stream) используя алгоритм Deflate.
GZipStream Предоставляет методы и свойства использованные для сжатия и извлечения потоков (stream).
Обратите внимание, что этот класс введен в C# с версии 4.5, поэтому ваш проект должен использовать .NET с версией 4.5 или новее.

2- ZipFile

Zip File class - это утилитарный класс, имеет много статических методов, которые помогут вам открыть zip-файл, извлечь данные, или часто встречающиеся ситуации, как сжатие каталога в zip-файл, извлечение zip-файл в папку, ..
В приведенном ниже простом примере используются методы утилитарного класса ZipFile для сжатия папки в zip-файл и затем извлечения этого файла в другую папку.
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)
        {
            // Папка будет сжата.
            string inputDir = "C:/test/inputdir";

            // Выходной файл после сжатия файла выше.
            string zipPath = "C:/test/data.zip";

            // Извлечь файл zip в папку.
            string extractPath = "C:/test/outputdir";

            // Создать файлzip с помощью сжатия папки.
            ZipFile.CreateFromDirectory(inputDir, zipPath);

            // Извлечь файл zip в папку.
            ZipFile.ExtractToDirectory(zipPath, extractPath);

            Console.WriteLine("Done!");
        }
    }

}
Если вы получите сообщение об ошибке: "The name 'ZipFile' does not exist in the current context" (хотя вы объявили, что используете System.IO.Compression), это означает, что ваш проект использует версию старее  .NET 4.5 или программа не находит Библиотеку DLL. Вы можете увидеть, как исправить эту ошибку в аппендиксе в конце этой статьи.
Запуск примера и получение результата:
  • data.zip

3- ZipArchive

ZipArchive представляет собой пакет сжатых файлов в формате ZIP. Объект ZipArchive можно создать с помощью метода OpenRead класса ZipFile. Через ZipArchive вы можете прочитать подфайлы, сжатые в zip-файле.
В следующем примере перечислены ZipArchiveEntry, включенные в zip-файле.
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))
            {
                // Просмотр списка ZipArchiveEntry.
                foreach (ZipArchiveEntry entry in archive.Entries)
                {
                    Console.WriteLine("Entry:");
                    Console.WriteLine("  Name = " + entry.Name);
                    Console.WriteLine("  FullName = " + entry.FullName);
                }
            }

            Console.Read();
        }
    }

}
Запуск примера:
Извчечение файлоа данных в zip-файле:
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";

            // Выходная папка для извлечения.
            string extractPath = "c:/test/extract";

            // Создать папку, если она не существует.
            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);

                    // Поиск Entry с окончанием .docx
                    if (entry.FullName.EndsWith(".docx", StringComparison.OrdinalIgnoreCase))
                    {
                        // Пример: documents/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);

                        // Удостовериться, что папка содержащая этот файл существует.
                        // ie: C:/test/extract/documents
                        fileInfo.Directory.Create();

                        // Переопределить старый файл, если он уже существует.
                        entry.ExtractToFile(entryOuputPath,true);
                    }
                }
            }

            Console.ReadLine();
        }
    }

}
Запуск примера:
Вы так же можете поместить файлы в доступный zip-файл.
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";

            // Открыть Stream для чтения файла zip.
            using (FileStream zipStream = new FileStream(zipPath, FileMode.Open))
            {
                // Создать объект ZipArchive.
                using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update))
                {
                    // Добавить entry в ZipArchive.
                    ZipArchiveEntry readmeEntry = archive.CreateEntry("note/Note.txt");

                    // Создать Stream чтобы записать содержание в entry.
                    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                    {
                        writer.WriteLine("## Note.txt");
                        writer.WriteLine("========================");
                    }
                }
            }
        }
    }

}
Запуск примера и получение результата:

4- Аппендикс: Исправление ошибок

Если вы получите сообщение об ошибке: "The name 'ZipFile' does not exist in the current context" (хотя вы заявили, что используете System.IO.Compression), что означает, что ваш проект использует старую версию .NET 4.5 или программы не находит Библиотека DLL.
Щелкните правой кнопкой мыши на Project и выберите Properties, убедитесь, что ваш проект использует . NET Framework 4.5 или новее.
Перезапустите ваш класс и посмотрите выдается ли еще та ошибка. Если все ещё выдаёт ошибку, вам нужно определить положение библиотеки  DLL.
  • 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
Щелкните правой кнопкой мыши на Project и выберите:
  • Add/Reference..
Выберите файл:
  • System.IO.Compression.FileSystem.dll
Аналогичным образом, если вы получите уведомление: "The name 'ZipArchive' does not exist in the current context" (Даже когда уже объявили using System.IO.Compression) , вам необходимо объявить об использовании библиотеки System.IO.Compression.dll.
Аналогичным образом, если вы получите уведомление: " The name 'Path' does not exist in the current context" (Даже когда уже объявили using System.IO), вам необходимо объявить использование библиотеки mscorlib.dll.