Работа с ZIP/архивами в C# (.NET): полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Работа с ZIP-архивами в C# (.NET): полное руководство

В современной разработке на платформе .NET работа с архивами — одна из частых задач. Будь то упаковка логов, распаковка конфигураций или создание резервных копий — встроенные средства System.IO.Compression позволяют делать это эффективно и без сторонних библиотек. В этой статье мы разберём основные операции с ZIP-архивами на C#, включая сжатие, извлечение, добавление файлов и работу с потоками.

Необходимые пространства имён

Для работы с архивами в .NET используются два основных пространства имён:

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

Начиная с .NET Framework 4.5, класс ZipFile доступен в сборке System.IO.Compression.FileSystem. В .NET Core / .NET 5+ он входит в базовую библиотеку.

Создание ZIP-архива из файлов

Самый простой способ создать архив — использовать статический метод ZipFile.CreateFromDirectory. Он принимает путь к папке, путь к архиву и уровень сжатия.

string sourceFolder = @"C:\Temp\Documents";
string zipPath = @"C:\Temp\backup.zip";

// Создаём архив со сжатием Optimal
ZipFile.CreateFromDirectory(sourceFolder, zipPath, CompressionLevel.Optimal, false);

Console.WriteLine($"Архив создан: {zipPath}");

Параметры:

  • sourceFolder — исходная директория;
  • zipPath — путь к будущему архиву;
  • CompressionLevel — Optimal, Fastest или NoCompression;
  • includeBaseDirectory — если true, в архиве будет корневая папка.

Распаковка ZIP-архива

Извлечение файлов выполняется методом ZipFile.ExtractToDirectory:

string zipPath = @"C:\Temp\backup.zip";
string extractPath = @"C:\Temp\Restored";

// Распаковываем с перезаписью существующих файлов
ZipFile.ExtractToDirectory(zipPath, extractPath, overwriteFiles: true);

Console.WriteLine("Архив распакован.");

В .NET 6+ появился параметр overwriteFiles, позволяющий перезаписывать файлы без исключения.

Добавление файлов в существующий архив

Класс ZipArchive даёт полный контроль над содержимым. Откроем архив в режиме обновления и добавим новый файл:

string zipPath = @"C:\Temp\backup.zip";
string newFile = @"C:\Temp\newDocument.txt";

using (FileStream zipStream = new FileStream(zipPath, FileMode.Open, FileAccess.ReadWrite))
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Update))
{
    // Создаём запись в архиве
    ZipArchiveEntry entry = archive.CreateEntry("newDocument.txt");

    using (StreamWriter writer = new StreamWriter(entry.Open()))
    {
        writer.Write("Это содержимое нового файла.");
    }

    Console.WriteLine($"Файл {newFile} добавлен в архив.");
}

Важно: при использовании ZipArchiveMode.Update архив должен быть открыт для чтения и записи.

Чтение содержимого архива без распаковки

Иногда нужно просто посмотреть, какие файлы внутри. Для этого перебираем записи архива:

string zipPath = @"C:\Temp\backup.zip";

using (FileStream zipStream = new FileStream(zipPath, FileMode.Open, FileAccess.Read))
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Read))
{
    foreach (ZipArchiveEntry entry in archive.Entries)
    {
        Console.WriteLine($"Файл: {entry.FullName}, Размер: {entry.Length} байт");
    }
}

Свойство FullName содержит путь внутри архива, включая подпапки.

Работа с потоками: сжатие и распаковка в памяти

Для сценариев, когда архив нужно передать по сети или сохранить в базу данных, удобно использовать MemoryStream:

// Сжатие строки в архив в памяти
using (MemoryStream ms = new MemoryStream())
{
    using (ZipArchive archive = new ZipArchive(ms, ZipArchiveMode.Create, leaveOpen: true))
    {
        ZipArchiveEntry entry = archive.CreateEntry("data.txt");
        using (StreamWriter writer = new StreamWriter(entry.Open()))
        {
            writer.Write("Hello, ZIP from memory!");
        }
    }

    byte[] zipBytes = ms.ToArray();
    Console.WriteLine($"Размер архива в памяти: {zipBytes.Length} байт");
}

Параметр leaveOpen: true оставляет поток открытым после закрытия архива.

Обработка ошибок и безопас

Рекомендаций