уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Про работу с zip в Delphi 10.3 Rio я писал не так давно. На днях потребовалось использовать возможности работы с zip в Lazarus. Чем не повод рассмотреть возможные решения для работы с zip в Lazarus и Free Pascal, а, заодно, попытаться сравнить удобство/качество того или иного решения? Конечно, сравнение будет носить чисто субъективный характер, но, тем не менее, может кому-то поможет сделать выбор в сторону того, какую библиотеку для работы с zip-файлами в Lazarus выбрать.

1. ZipFile

Информация об этом пакете имеется на страничке wiki Lazarus и это было первое решение, которое я решил протестировать. Однако, насторожила дата последнего изменения архива на SourceForge — 2006-11-10. И не зря, так как попытка скомпилировать пакет привела к ошибке:

Fatal: Невозможно найти Laz_AVL_Tree, используемый в LCLProc, несовместимый PPU=C:\lazarus\components\lazutils\lib\x86_64-win64\laz_avl_tree.ppu, пакет LazUtils

Я не стал углубляться в поиск решения этой проблемы (возможно, на досуге разберусь, что с этим делать) и перешел к следующему решению по работе с 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 и оставили вполне положительное впечатление о себе.

5 2 голоса
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии