Содержание
Формат zip — наиболее популярный формат архивации файлов и было бы странным, если бы в C# не было готовых классов для работы с zip-архивами. Все необходимые классы для работы с архивами zip в C# располагаются в пространстве имен System.IO.Compression
.
Методы управления ZIP-архивами распределены по трем классам: ZipFile
, ZipArchive
и 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}"); }
Здесь мы перечислили все элементы архива и вывели информацию о них в консоль. В консоль будет отправлен примерно такой вывод:
Имя файла: 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
. Результат в консоли будет следующим:
Размер файла: 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-архиве.