Работа с архивами zip в C#

Формат zip — наиболее популярный формат архивации файлов и было бы странным, если бы в C# не было готовых классов для работы с zip-архивами. Все необходимые классы для работы с архивами zip в C# располагаются в пространстве имен System.IO.Compression.

Методы управления ZIP-архивами распределены по трем классам: ZipFileZipArchive и ZipArchiveEntry.

Класс ZipFile

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

  • CreateFromDirectory() — создает zip-архив из каталога
  • ExtractToDirectory() — извлекает файлы из архива в указанный каталог
  • Open() — открывает архив для работы с ним и возвращает объект типа ZipArchive
  • OpenRead() — открывает архив только для чтения и возвращает объект типа ZipArchive 

Рассмотрим работу этих методов на примерах.

Как создать zip-архив каталога в C#?

string sourcePath = @"c:\temp\";
string targetPath = @"c:\archive";//папка должна существовать на диске
ZipFile.CreateFromDirectory(sourcePath, Path.Combine(targetPath, "archive.zip"));

В результате будет создан архив, содержащий все файлы, находящиеся в каталоге sourcePath. При этом сам каталог в архив не включается (только файлы, находящиеся в нем).

Как создать zip-архив каталога, указав уровень сжатия файлов в C#?

string sourcePath = @"c:\temp\";
string targetPath = @"c:\archive";//папка должна существовать на диске
//Архив с минимальным размером
ZipFile.CreateFromDirectory(sourcePath, Path.Combine(targetPath, "archive_min.zip"), CompressionLevel.SmallestSize, false);
//Архив должен быть создан максимально быстро
ZipFile.CreateFromDirectory(sourcePath, Path.Combine(targetPath, "archive_fast.zip"), CompressionLevel.Fastest, false);
//Архив должен быть создан за оптимальное время с оптимальным размером (настройка по умолчанию)
ZipFile.CreateFromDirectory(sourcePath, Path.Combine(targetPath, "archive_optimal.zip"), CompressionLevel.Optimal, false);
//Архив создается без сжатия файлов
ZipFile.CreateFromDirectory(sourcePath, Path.Combine(targetPath, "archive_no_compress.zip"), CompressionLevel.NoCompression, false);
Console.WriteLine("Архив создан");

В данном случае, мы воспользовались перегруженной версией метода CreateFromDirectory, указав в качестве третьего параметра значение перечисления CompressionLevel, благодаря которому мы настраиваем уровень сжатия файлов и желаемую скорость сжатия. Четвертый параметр метода указывает на то, будет ли в архив включаться каталог, указанный в первом параметре или же, как в примере выше, в архив будут включаться только файлы из него.

Как распаковать zip-архив в C#?

string archiveFilePath = @"C:\temp\archive.zip"; //полный путь к файлу архива
string targetFolder = @"c:\temp\";//путь к папке в которую будет распакован архиа
bool overriteFiles = true; //перезаписать файлы, если они уже есть в папке нахначения
ZipFile.ExtractToDirectory(archiveFilePath, targetFolder, overriteFiles);

Классы ZipArchive и ZipArchiveEntry

Класс ZipArchive представляет zip-архив с файлами, в то время как класс ZipArchiveEntry представляет отдельный файл внутри архива. Используя эти классы мы можем:

  • изучать содержимое архива
  • извлекать отдельные файлы из архива
  • добавлять файлы в архив
  • добавлять комментарии к архиву

Рассмотрим как мы можем работать с объектами типа ZipArchive и ZipArchiveEntry в C#.

Как создать объект типа ZipArchive в C#?

Чтобы создать объект типа ZipArchive для работы с zip-архивом, необходимо либо воспользоваться методами класса ZipFile, либо использовать один из конструкторов класса ZipArchive, указав в обоих случаях режим работы с архивом. Рассмотрим оба варианта.

Создание объекта ZipArchive с использованием методов ZipFile

Открыть zip-архив для чтения и записи файлов:

string archivePath = @"c:\archive\archive_min.zip";
ZipArchive archive = ZipFile.Open(archivePath, ZipArchiveMode.Update);

Открыть zip-архив только на чтение:

string archivePath = @"c:\archive\archive_min.zip";
ZipArchive archive = ZipFile.OpenRead(archivePath);

Второй параметр метода Open — это перечисление типа ZipArchiveMode, для которого определены следующие значения:

public enum ZipArchiveMode
{
    //только чтение содержимого архива
    Read = 0,
    //только создание архива
    Create = 1,
    //чтение и запись архива
    Update = 2
}

Создание объекта ZipArchive с использованием конструктора

Чтобы создать объект типа ZipArchive с использованием одного из конструкторов класса, нам необходимо передать в конструктор поток (Stream), содержащий данные архива. Например:

string archivePath = @"c:\archive\archive_min.zip";
using var fileStream = File.Open(archivePath,FileMode.Open);
ZipArchive archive = new ZipArchive(fileStream);
//ИЛИ
ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Update);

Как перечислить все файлы, находящиеся в zip-архиве?

После того, как создан объект типа ZipArchive мы можем работать с его свойствами и методами. Перечислим все файлы, находящиеся в zip-архиве:

string archivePath = @"c:\archive\archive_min.zip";
using var fileStream = File.Open(archivePath,FileMode.Open);
ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Update);
foreach (ZipArchiveEntry entry in archive.Entries) 
{
    if (entry.Name != "")
        Console.WriteLine($"Имя файла: {entry.Name} Размер сжатого файла: {entry.CompressedLength} Контрольная сумма: {entry.Crc32}");
    else
        Console.WriteLine($"Папка: {entry.FullName}");
}

Здесь мы перечислили все элементы архива и вывели информацию о них в консоль. В консоль будет отправлен примерно такой вывод:

Имя файла: 002.jpg Размер сжатого файла: 589355 Контрольная сумма: 3407861831
Имя файла: data.txt Размер сжатого файла: 132 Контрольная сумма: 4267209921
Имя файла: debug.log Размер сжатого файла: 1205 Контрольная сумма: 3194343811
Имя файла: 002.jpg Размер сжатого файла: 589355 Контрольная сумма: 3407861831
Имя файла: data.txt Размер сжатого файла: 132 Контрольная сумма: 4267209921
Папка: debug/debug/
Имя файла: debug.log Размер сжатого файла: 1205 Контрольная сумма: 3194343811

Стоит обратить внимание на то, что папки (каталоги) также отражаются в коллекции Entries архива, но, в отличие от файлов не содержат свойств размера и имени (только свойство FullName)

Как получить детальную информацию о файле из zip-архива?

Попробуем найти в архиве определенный файл и вывести всю доступную информацию о нем в консоль.

string archivePath = @"c:\archive\archive_min.zip";
using var fileStream = File.Open(archivePath,FileMode.Open);
ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Update);
string fileName = "debug.log";
var file = archive.Entries.Where(s=>s.Name == fileName).FirstOrDefault();
if (file != null)
{
    Console.WriteLine($"Имя: {file.Name}");
    Console.WriteLine($"Полный путь в архиве: {file.FullName}");
    Console.WriteLine($"Размер файла: {file.Length}");
    Console.WriteLine($"Размер файла в сжатом состоянии: {file.CompressedLength}");
    Console.WriteLine($"Контрольная сумма CRC32: {file.Crc32}");
    Console.WriteLine($"Файл зашифрован: {file.IsEncrypted}");
    Console.WriteLine($"Комментарий к файлу: {file.Comment}");
}

Здесь мы воспользовались методом LINQ Where для поиска необходимого файла в коллекции Entries и, затем, перечислили все доступные свойства объекта ZipArchiveEntry. Результат в консоли будет следующим:

Имя: debug.log Полный путь в архиве: debug.log
Размер файла: 10579
Размер файла в сжатом состоянии: 1205
Контрольная сумма CRC32: 3194343811
Файл зашифрован: False
Комментарий к файлу:

Как извлечь определенный файл из zip-архива?

Для того, чтобы извлечь определенный файл из архива, мы должны воспользоваться методом ExtractToFile объекта ZipArchiveEntry. Например

            string archivePath = @"c:\archive\archive_min.zip";
            using var fileStream = File.Open(archivePath,FileMode.Open);
            ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Update);
            string fileName = "dump.sql";
            var file = archive.GetEntry(fileName);
            if (file != null)
            {
                file.ExtractToFile(Path.Combine(@"C:\archive", fileName)); 
            }

В этом примере мы уже не пользовались LINQ для поиска файла, а использовали метод класса ZipArchive.GetEntry и, затем, извлекли найденный файл из архива в указанную папку.

Как добавить новый файл в существующий zip-архив?

Ниже представлен один из примеров того, как добавить новый файл в существующий zip-архив

string archivePath = @"c:\archive\archive_min.zip";
using var fileStream = File.Open(archivePath,FileMode.Open);
using ZipArchive archive = new ZipArchive(fileStream, ZipArchiveMode.Update);
string filePath = @"C:\archive\config.ini";
string archiveEntryName = "data.ini";
//создаем новый элемент архива
archive.CreateEntryFromFile(filePath, archiveEntryName);

используя класс ZipFile, ту же самую операцию можно сделать немного короче:

string archivePath = @"c:\archive\archive_min.zip";
using ZipArchive archive = ZipFile.Open(archivePath, ZipArchiveMode.Update);
string filePath = @"C:\archive\config.ini";
string archiveEntryName = "data.ini";
//создаем новый элемент архива
archive.CreateEntryFromFile(filePath, archiveEntryName);

Итого

Для работы с zip-файлами в C# предназначены три класса — ZipFile, ZipArchive и ZipArchiveEntry. Используя эти классы мы можем создавать архивы из каталогов на диске, получать детальную информацию о файлах, находящихся в zip-архиве, добавлять или удалять файлы zip-архива, добавлять или удалять комментарии как к архиву в целом, так и для отдельных элементов (файлов) в zip-архиве.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии