
Архивация
Техника работы из библиотекой zLib основана на потоках. Библиотека экспортирует класс TCustomZLibStream - потомок класса TStream. Класс TCustomZLibStream в свою очередь является родителем для TCompressionStream и TDecompressionStream. Работа с этими классами стандартна, и внимания заслуживают только их конструкторы.
Класс TCompressionStream для упаковки данных имеет конструктор:
constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream)
Тут перечисление:
TCompressionLevel = (clNone, clFastest, clDefault, clMax)
– степень сжатия, а Dest – поток назначения, куда будут записываться заархивированные данные.
Класс TDecompressionStream для распаковки имеет конструктор:
constructor Create(Source: TStream);
Тут Source – потока назначения, куда будут записываться распакованные данные.
Классы TCompressionStream и TDecompressionStream работают "на лету" в том смысле, что упаковка/распаковка и запись в принимающий поток осуществляется сразу по мере того как данные поступают на вход класса (для TCompressionStream) или считываются из него (для TDecompressionStream).
Замечание: Для того, чтобы во время работы программы не создавалось впечатление "подвисания" программы, я процедуры архивации и распаковки засунул в отдельные подпроцессы – нити.
Я не использовал встроенные средства в Delphi для работы с нитями, а воспользовался своими любимыми API-функциями. Для создания нити используется CreateThread:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // дескриптор защиты
SIZE_T dwStackSize, // начальный размер стека
LPTHREAD_START_ROUTINE lpStartAddress, // функция потока
LPVOID lpParameter, // указатель переменной, что может передаваться в поток
DWORD dwCreationFlags, // опции создания
LPDWORD lpThreadId // идентификатор потока
);
Это определение я взял из MSDN, думаю, оно вполне понятно. Для нас важны параметры lpStartAddress, и dwCreationFlags.
-Параметр lpStartAddress – это указатель на функцию, которая будет выполняться в потоке.
-Параметр dwCreationFlags – определяет условия создания потока. Если установить сюда значение CREATE_SUSPENDED, то создается поток в состоянии ожидания и не запускается до тех пор, пока не будет вызвана функция ResumeThread. Если это значение нулевое, поток запускается немедленно после создания. В это время, никакие другие значения не поддерживаются.
-Функция CreateThread вовращает дескриптор потока, который мы можем использовать для различных целей (например, поменять приоритет или "прибить" поток функцией TerminateThread).
Практическая часть
Функция архивации:
function TForm1.SaveToZUP(filein,fileout:string;compression:TCompressionLevel):boolean;
Var //filein,fileout - входной и выходной файлы;
//compression - степень сжатия
ms:TMemoryStream; //вспомогательный поток, куда будет загружен входной filein
OutFile:TStream; //выходной поток, сюда поток архивации записывает сжатые данные
ZStream: TCustomZLibStream; //поток архивации (взял абстрактный)
filename:string[255]; //имя входного файла, его запишем в заголовок архива
begin
try
ms:=TMemoryStream.Create; //создание потока
ms.LoadFromFile(filein); //грузим входной файл в поток
OutFile:=TFileStream.Create(Fileout,fmCreate); //создадим пустой файл архива
filename:=ExtractFileName(filein); //выделим имя
OutFile.Write(filename,sizeof(filename)); //запишем в заголовок архива имя
try //создание архивирующего потока, запись данных будет идти в OutFile
ZStream:=TCompressionStream.Create(compression,OutFile);
try
ZStream.CopyFrom(ms,0); //копируем весь входной файл в архивирующий поток
//параллельно идет запись в OutFile
finally
ZStream.Free;
end;
finally
ms.free;
OutFile.Free;
result:=true;
end;
except result:=false;
end;
end;