Про работу с zip в Delphi 10.3 Rio я писал не так давно. На днях потребовалось использовать возможности работы с zip в Lazarus. Чем не повод рассмотреть возможные решения для работы с zip в Lazarus и Free Pascal, а, заодно, попытаться сравнить удобство/качество того или иного решения? Конечно, сравнение будет носить чисто субъективный характер, но, тем не менее, может кому-то поможет сделать выбор в сторону того, какую библиотеку для работы с zip-файлами в Lazarus выбрать.
1. ZipFile
Информация об этом пакете имеется на страничке wiki Lazarus и это было первое решение, которое я решил протестировать. Однако, насторожила дата последнего изменения архива на SourceForge — 2006-11-10. И не зря, так как попытка скомпилировать пакет привела к ошибке:
Я не стал углубляться в поиск решения этой проблемы (возможно, на досуге разберусь, что с этим делать) и перешел к следующему решению по работе с zip в Lazarus.
2. Zlibar
Скачать архив можно здесь. Дата последнего изменения на SourceForge — 2012-02-24.
Распаковываем архив в удобное место, открываем в Lazarus файл пакета «zlibar_package.lpk» и жмем «Компилировать»:
Компиляция на Lazarus 2.0.8 прошла успешно. Попробуем протестировать zlibar на предмет работы с zip-архивами в Lazarus. Для этого создаем новый проект в Lazarus и в окне пакета zlibar выбираем «Использовать — Добавить к проекту»:
В исходном коде проекта появится модуль zlibar_package:
Теперь, для того, чтобы использовать возможности zlibar по работе с zip-архивами нам необходимо подключить в uses модуля приложения модуль zlibar, например, так:
Для работы с zip-архивами в zlibar предусмотрено два класса:
{Класс для создания zip-архива} TZlibWriteArchive = class(TObject) public constructor Create; destructor Destroy; override; public function CreateArchive: boolean; property OnError: TZlibErrorProc read fOnError write fOnError; property OnCompress : TZlibCompressProgProc read fOnCompress write fOnCompress; published property OutStream: TStream read fStream write SetStream; property InputFiles: TZlibFilesList read fInputFiles; end; {Класс для чтения zip-архива} TZLibReadArchive = class(TObject) public constructor Create; constructor Create(InStream: TStream); destructor Destroy; override; public procedure ExtractFileToStream(AIndex: Integer; Stream: TStream); procedure ExtractFileToStream(const AFileName: String; Stream: TStream); procedure ExtractFileToStream(const AFileName , APath: String; Stream: TStream); property Header: TZlibArchiveHeader read fHeader; property FilesInArchive[Index: Integer]: TTOCEntry read GetTOCEntry; property Count: Integer read GetCount; property OnError: TZlibErrorProc read fOnError write fOnError; property OnExtract: TZlibExtractProgProc read fOnExtract write fOnExtract; published property InStream: TStream read fStream write SetStream; end;
При работе с большими архивами можно использовать следующие события:
{При архивации фалов в zip-архив} TZlibCompressProgProc = procedure (Sender: TObject; FileIndex: Integer; FileSize, FilePos: Int64) of object; {при распаковке Zip-архива} TZlibExtractProgProc = procedure (Sender: TObject; FileSize, FilePos: Int64) of object; {при возникновении ошибок архивации/разархивации} TZlibErrorProc = procedure(Sender: TObject; var ErrorCode: Integer; ErrorStr: String) of object;
На страничке wiki, посвященной работе с zlibar есть два простеньких примера работы с этими классами в Lazarus. Я решил воспользоваться ими и посмотреть на работу zlibar. Вот такой код у меня получился на создания zip-архива в Lazarus:
var MyZip: TZlibWriteArchive; Stream: TMemoryStream; begin Stream := TMemoryStream.Create(); try MyZip := TZlibWriteArchive.Create; try MyZip.OutStream := Stream; //добавляем файлы для упаковки MyZip.InputFiles.Add('appnote.txt'); //создаем архив MyZip.CreateArchive; //сохраняем архив Stream.SaveToFile('archive.zip'); finally FreeAndNil(MyZip) end; finally FreeAndNil(Stream); end; end;
и, соответственно, распаковку zip-архива (код взят с wiki):
var ArchStream: TMemoryStream; FileStream: TMemoryStream; ZReadArc: TZlibReadArchive; X: integer; DestPath: string; begin ArchStream := TMemoryStream.Create; //поток для zip-файла FileStream := TmemoryStream.Create; //поток для распакованного файла ArchStream.LoadFromFile('archive.zip'); //загружаем архив в поток ZReadArc := TZlibReadArchive.Create(ArchStream);//создаем объект для работы с архивом DestPath := ExtractFilePath(ParamStr(0));//путь по которому будут сохраняться файлы {Распаковываем файлы с сохранением их пути в архиве} for X := 0 to ZReadArc.Count - 1 do begin ZReadArc.ExtractFileToStream(X, FileStream); FileStream.SaveToFile(DestPath + ZReadArc.FilesInArchive[X].FilePath + '/' + ZReadArc.FilesInArchive[X].FIleName); FileStream.Position := 0; FileStream.Size := 0; end; ZReadArc.Free; ArchStream.Free; FileStream.Free; end;
Что в итоге получилось: создался архив с названием archive.zip, который не читается штатными средствами Windows 10:
При этом распаковка архива средствами zlibar прошла успешно — файл распаковался, не испортился.
Таким образом, для себя я сделал следующий вывод по zlibar: использовать можно, но осторожно и только при условии, что с созданными архивами будет работать только моя программа.
3. Компоненты TurboPower Abbrevia
Скачать компоненты можно здесь. Дата последнего изменения на SourceForge — 2014-06-11.
Также, эти компоненты можно установить, используя сетевой диспетчер пакетов Lazarus. Для этого, в меню Lazarus выбираем «Пакет — Сетевой диспетчер пакетов» и, в открывшемся окне ищем компоненты Abbrevia:
После этого, нажимаем в сетевом диспетчере кнопку «Установить» — «Из репозитория»:
Lazarus скачает и распакует архив и установит компоненты, после чего IDE будет пересобрана:
После пересборки IDE Lazarus на панели компонентов появится новая вкладка Abbrevia, содержащая необходимые компоненты для работы с zip-архивами в Lazarus, а также с CAB-файлами:
Для того, чтобы создать zip-архив в Lazarus, можно воспользоваться компонентом TAbUnZipper. Бросаем его на форму и пишем вот такой код:
AbZipper1.FileName:='archive.zip'; AbZipper1.AddFiles('*.txt',faAnyFile); AbZipper1.Save; AbZipper1.CloseArchive;
Здесь мы задали имя zip-архива, указали компоненту, что надо упаковать все файлы с расширением txt и сохранили полученный архив. То есть я провел ровно ту же операцию, что и при работе с предыдущей библиотекой zlibar. Соответственно, если требуется взять файлы для архива из какой-либо другой директории отличной от той, в которой лежит exe-файл вашей программы, то компоненту перед созданием архива необходимо эту директорию указать в свойстве BaseDirectory, например, так:
AbZipper1.BaseDirectory:='path\to\my\files';
Распаковывается zip-архив с использованием компонента TAbUnZipper следующим образом:
AbUnZipper1.FileName:='archive.zip'; AbUnZipper1.ExtractFiles('*.txt');
Созданные с помощью компонентов Abbrevia архивы без ошибок читаются штатными средствами Windows 10.
Что понравилось: компоненты достаточно просты в использовании, без проблем устанавливаются в Lazarus 2.0.8, имеют достаточно много полезных свойств, типа поиска файлов по маске, использование лог-файла работы и т.д. Вполне возможно, что когда-нибудь рассмотрю эти компоненты более подробно в блоге.
4. Модуль Zipper
Для работы с zip-файлами в Lazarus и Free Pascal используются классы TZipper и TUnZipper, содержащиеся в модуле zipper. Достаточно подключить этот модуль в проект и можно работать с zip-архивами в Lazarus и FPC. Так можно создать zip-архив:
var Zipper: TZipper; begin Zipper:=TZipper.Create; try Zipper.FileName:='archive.zip'; Zipper.Entries.AddFileEntry('appnote.txt'); Zipper.ZipAllFiles; finally FreeAndNil(Zipper) end; end;
Соответственно, распаковка происходит с использованием TUnZipper вот так:
var UnZipper: TUnZipper; begin UnZipper:=TUnZipper.Create; try UnZipper.FileName:='archive.zip'; UnZipper.UnZipAllFiles; finally FreeAndNil(UnZipper) end; end;
По своим возможностям Zipper очень сильно напоминает TZipFile в Delphi. В плане использования у меня никаких проблем также не возникло — с теми функциями, которые мне нужны при работе с zip-архивами в Lazarus Zipper справился без проблем, а, учитывая наличие различных свойств и событий у классов, думаю, что Zipper и будет тем самым решением для работы с zip в lazarus, которое я и буду в дальнейшем использовать в работе.
Результаты
Итого, из четырех рассмотренных вариантов работы с zip в lazarus, одно решение (zipfile) вообще не подошло, так как проект, видимо, давным давно умер. Одно решение подошло частично, т.к. созданный в zlibar архив отказался читаться штатными средствами Windows (возможно в Debian/Linux проблем не будет — пока не проверял). Два решения (Zipper и компоненты Abbrevia) с задачей справились — архивы собираются, читаются. Что касается удобства использования того или иного решения, то, как сказал выше, это чисто субъективное мнение. Лично для себя я давно сделал простой вывод — если штатные средства позволяют выполнить задачу на 100%, то не стоит искать какие-то прочие решения на стороне. Поэтому в дальнейшем я буду использовать в Lazarus модуль Zipper, хотя компоненты Abbrevia и оставили вполне положительное впечатление о себе.