|
Вопрос # 953/ вопрос открыт / |
|
Здравствуйте, эксперты!
Вопрос про архиватор. Мне требуется архивировать файлы различного размера. Это одна из многих функций - далеко не основная. Я использую готовое решение by Andrea Russo - Italy - 2005, выдранное из инета (исходники прикладываю). Проблема в том, что на разархивирование времени уходит болше чем на архивирование. Более того, с ростом размера файла к примеру от 100 мег до 600 мег время разархивирования увеличивается нелинейно (не в 6 а примерно в 15-20 раз) и в конечном итоге составляет до 1,5-2 часа.
Есть ли другие готовые решения (с исходниками) или как изменить это, чтобы поднять скорость архивирования - разархивирования скажем до 50-100 Мбайт в минуту с разными коэффициентами сжатя.
Приложение: Переключить в обычный режим- <code>
- unit UtilityPasZlib;
-
- // by Andrea Russo - Italy - 2005
- // email: andrusso@libero.it
-
- interface
-
- //Unit zlib is icluded into the latest version of Delphi (from Delphi 6), but in old versions is
- //included into the Delphi cd.
- // Otherwise if do you want to use paszlib library change the uses.
-
- //If do you want to use zlib included into Delphi
-
- uses zlib, Classes;
-
- //If do you want to use paszlib library
- //uses dzlib, Classes;
-
- type TCompLevel = (clNone, clFastest, clDefault, clMax);
-
- procedure CompressFile(const sFileIn : string; const sFileOut : string; const Level : TCompLevel =
clDefault);
- procedure UnCompressFile(const sFileIn : string; const sFileOut : string);
-
- procedure CompressStream(inStream, outStream :TStream; const Level : TCompLevel = clDefault);
- procedure ExpandStream(inStream, outStream :TStream);
-
- implementation
-
- procedure CompressFile(const sFileIn : string; const sFileOut : string; const Level : TCompLevel =
clDefault);
- var
- inStream, outStream: TMemoryStream;
- begin
- inStream:=TMemoryStream.Create;
- outStream:=TMemoryStream.Create;
- try
- inStream.LoadFromFile(sFileIn);
- with TCompressionStream.Create(TCompressionLevel(Level), outStream) do
- try
- CopyFrom(inStream, inStream.Size);
- finally
- Free;
- end;
- outStream.SaveToFile(sFileOut);
- finally
- outStream.Free;
- inStream.Free;
- end;
- end;
-
- procedure UnCompressFile(const sFileIn : string; const sFileOut : string);
- var
- inStream, outStream: TMemoryStream;
- begin
- inStream:=TMemoryStream.Create;
- outStream:=TMemoryStream.Create;
- try
- inStream.LoadFromFile(sFileIn);
- ExpandStream(inStream, outStream);
- outStream.SaveToFile(sFileOut);
- finally
- inStream.Free;
- outStream.Free;
- end;
- end;
-
- procedure CompressStream(inStream, outStream :TStream; const Level : TCompLevel = clDefault);
- begin
- with TCompressionStream.Create(TCompressionLevel(Level), outStream) do
- try
- CopyFrom(inStream, inStream.Size);
- finally
- Free;
- end;
- end;
-
- procedure ExpandStream(inStream, outStream :TStream);
- const
- BufferSize = 4096;
- var
- Count: integer;
- ZStream: TDecompressionStream;
- Buffer: array[0..BufferSize-1] of Byte;
- begin
- ZStream:=TDecompressionStream.Create(InStream);
- try
- while true do
- begin
- Count:=ZStream.Read(Buffer, BufferSize);
- if Count<>0
- then OutStream.WriteBuffer(Buffer, Count)
- else Break;
- end;
- finally
- ZStream.Free;
- end;
- end;
-
- end.
- </code>
 |
Вопрос задал: Popovich E.V. (статус: Посетитель)
Вопрос отправлен: 3 октября 2007, 15:58
Состояние вопроса: открыт, ответов: 4.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, Popovich E.V.!
Причиной стремительного замедления может быть неудачная работа с памятью
для примера, потестируйте код
s:string;
begin
s:='';
for i:=1 to 1000 do s:=s+'*';
и код
s:string;
begin
s:='';
Setlength(s,1000)
for i:=1 to 1000 do s[i]:='*';
Хотя оба кода делают одно и тоже, но при увеличении строки первый код начинает подтормаживать. причина - постоянное копирование строки.
И хотя это жутко утрированный пример, но он в том или ином подобии появляется в разных примерах.
Второй причиной может быть то, что библиотека не расчитана на такие объёмы. тоесть при таких объемах данных может не совсем правильно заполнятся внутринее структуры, неправильно срабатывать оптимизация, которая хорошо работала на маленьких объема.
Есть альтернативная, бесплатная библиотека http://www.delphilab.ru/content/view/72/73/
скорость достаточно приличная (на 2ГГц даёт до мегабайта в секунду на распаковку)
Работает достаточно хорошо
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 3 октября 2007, 16:22
Оценка за ответ: 4
|
Ответ #2. Отвечает эксперт: Feniks
Здравствуйте, Popovich E.V.!
Сегодня в инете встретил книгу "Методы сжатия данных. Устройство архиваторов, сжатие изображений и видео" по этому адресу http://ru-admin.net/2007/10/03/metody-szhatija-dannykh.-ustrojjstvo.html
А кто Вам мешает использовать уже существующие архиваторы ? Ведь они все поддерживают работу с командной строкой, например RAR. Он есть и консольный. Консольным с помощью параметров командной строки пакует, а для распаковки используете его библиотеку unrar.dll Пример ее использования см. в Приложении.
Еще попробуйте пару компонентов http://depositfiles.com/files/1951946
Приложение: Переключить в обычный режим- function RAROpenArchive(ArchiveData : Pointer): Integer; stdcall;
- external 'unrar.dll' name 'RAROpenArchive';
-
- function RARCloseArchive(hArcData : Integer): Integer; stdcall;
- external 'unrar.dll' name 'RARCloseArchive';
-
- function RARReadHeader(hArcData : Integer; HeaderData : Pointer): Integer; stdcall;
- external 'unrar.dll' name 'RARReadHeader';
-
- function RARProcessFile(hArcData : Integer; Operation : Integer; DestPath : Pointer;
- DestName : Pointer): Integer; stdcall;
- external 'unrar.dll' name 'RARProcessFile';
-
-
- const
-
- ERAR_END_ARCHIVE = 10;
- ERAR_NO_MEMORY = 11;
- ERAR_BAD_DATA = 12;
- ERAR_BAD_ARCHIVE = 13;
- ERAR_UNKNOWN_FORMAT = 14;
- ERAR_EOPEN = 15;
- ERAR_ECREATE = 16;
- ERAR_ECLOSE = 17;
- ERAR_EREAD = 18;
- ERAR_EWRITE = 19;
- ERAR_SMALL_BUF = 20;
-
- RAR_OM_LIST = 0;
- RAR_OM_EXTRACT = 1;
- RAR_SKIP = 0;
- RAR_TEST = 1;
- RAR_EXTRACT = 2;
- RAR_VOL_ASK = 0;
- RAR_VOL_NOTIFY = 1;
-
-
- type
-
- Char260 = Array [1..260] of Char;
-
-
- TRAROpenArchiveData = record
-
- OpenMode : Cardinal;
- OpenResult : Cardinal;
- CmtBuf : PChar;
- CmtBufSize : Cardinal;
- CmtSize : Cardinal;
- CmtState : Cardinal;
- end;
-
-
-
- TRARHeaderData = record
- ArcName : Char260;
- FileName : Char260;
- Flags : Cardinal;
- PackSize : Cardinal;
- UnpSize : Cardinal;
- HostOS : Cardinal;
- FileCRC : Cardinal;
- FileTime : Cardinal;
- UnpVer : Cardinal;
- Method : Cardinal;
- FileAttr : Cardinal;
- CmtBuf : PChar;
- CmtBufSize : Cardinal;
- CmtSize : Cardinal;
- CmtState : Cardinal;
- end;
-
-
- var
-
- RARExtract : boolean;
- RAROpenArchiveData : TRAROpenArchiveData;
- RARComment : array [1..256] of Char;
- RARHeaderData : TRARHeaderData;
-
-
- ...
-
-
- procedure ExtractRARArchive;
- var
- sDir : string;
- s : string;
- sTest : string;
- iTest : integer;
- bTestDone : boolean;
- RARhnd : Integer;
- RARrc : Integer;
- PDestPath : Char260;
-
- begin
- RARExtract:=TRUE;
- lKBWritten:=0;
- ProgressBar2.Position := 0;
- ProgressBar2.Max := lTotalSize;
- RARStartTime:=Time;
-
- RAROpenArchiveData.OpenResult:=99;
-
- RAROpenArchiveData.ArcName:= @RARFileName;
- RAROpenArchiveData.CmtBuf := @RARComment;
- RAROpenArchiveData.CmtBufSize := 255;
-
-
- RARhnd := RAROpenArchive (@RAROpenArchiveData);
- If RAROpenArchiveData.OpenResult <> 0 then
- begin
- case RAROpenArchiveData.OpenResult of
- ERAR_NO_MEMORY : s:='Not enough memory to initialize data structures';
- ERAR_BAD_DATA : s:='Archive header broken';
- ERAR_BAD_ARCHIVE : s:='File is not valid RAR archive';
- ERAR_EOPEN : s:='File open error';
- end;
- MessageDlg('Unable to open rar archive: ' + s + '!',mtError, [mbOK], 0);
- end;
-
- RARSetProcessDataProc(RARhnd,@Form.OnRarStatus);
- StrPCopy(@PDestPath, EInstallPath.Text);
-
- repeat
-
- if RARrc <> ERAR_END_ARCHIVE then
- begin
- ProgressBar1.Position := 0;
- ProgressBar1.Max := RARHeaderData.UnpSize;
- s:=RARHeaderData.FileName;
- lblCurrentFile.Caption := s;
- lKBytesDone := 0;
- end;
-
- if RARrc = 0 then
- RARrc:=RARProcessFile (RARhnd, RAR_EXTRACT, @PDestPath, nil);
- if (RARrc <> 0) and (RARrc <> ERAR_END_ARCHIVE) then
- begin
- MessageDlg('An Error occured during extracting of ' + sTest+'!' + #13#10 +
- 'RARProcessFile: ' + MakeItAString(RARrc),mtError, [mbOK], 0);
- end;
- until RARrc <> 0;
-
-
- If RARCloseArchive(RARhnd) <> 0 then
- begin
- MessageDlg('Unable to close rar archive!',mtError, [mbOK], 0);
- end;
- end; // ExtractRARArchive
 |
Ответ отправил: Feniks (статус: Бакалавр)
Время отправки: 3 октября 2007, 16:39
|
Ответ #3. Отвечает эксперт: min@y™
Зайди-ка вот сюды. Там есть куча того, что тебе надо.
 |
Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 3 октября 2007, 16:50
|
Ответ #4. Отвечает эксперт: Помфюк Владимир Степанович
Здравствуйте, Popovich E.V.!
В Вашем примере совершенно непонятно зачем используется TMemoryStream. Возможно при болших обьёмах именно он и "тормозит процесс". Попробуйте так (в приложении). У меня работает, правда, с алгоритмом упаковки bz2 (BZip2 unit by Edison Mera, окуда качал не помню).
Приложение: Переключить в обычный режим-
-
- zs:TCompressionStream;
- ifl,ofl:TFileStream;
- begin
- ifl:=TFileStream.Create(InFileName,fmOpenRead);
- ofl:=TFileStream.Create(OutFileName,fmCreate or fmOpenReadWrite);
- zs:=TCompressionStream.Create(CompressionLefel,ofl);
- zs.CopyFrom(ifl,ifl.Size);
- ifl.Destroy;
- zs.Destroy;
- ofl.Destroy;
- end
-
-
Мини-форум вопроса
Всего сообщений: 1; последнее сообщение — 3 октября 2007, 16:45; участников в обсуждении: 1.
|
Feniks (статус: Бакалавр), 3 октября 2007, 16:45 [#1]:
В догонку, зыбал вставить...
В Delphi 7 официально включена поддержка библиотеки сжатия ZLib. Если у вас более старшая версия посмотрите модули ZLib в дестрибутиве среды (они должны быть на диске но подключать прийдеться самому).
Библиотеки под разные платформы, среды разработок и документация на сайте www.gzip.org/zlib.
Степень сжатия превосходит алгоритм zip. Максимальная степень сжатия по алгоритму ZLib приближается к степени сжатия упаковщиком RAR.
Модули Zlib, ZlibConst.
При использовании необходимо подключить в описании Uses модуль ZLib.
пример использования:
Компресия одного потока в другой:
ComressStream( aSource, aTarget : TStream; compressionRate : TCompressionLevel );
var comprStream : TCompressionStream;
begin
// compression level : (clNone, clFastest, clDefault, clMax)
comprStream := TCompressionStream.Create( compressionRate, aTarget );
try
comprStream.CopyFrom( aSource, aSource.Size );
comprStream.CompressionRate;
finally
comprStream.Free;
End;
End;
Декомпресия одного потока в другой:
DecompressStream(aSource, aTarget: TStream);
var decompStream : TDecompressionStream;
nRead : Integer;
buffer : array[0..1023] of Char;
begin
decompStream := TDecompressionStream.Create( aSource );
try
repeat
nRead:=decompStream.Read( buffer, 1024 );
aTarget.Write( buffer, nRead );
Until nRead = 0;
finally
decompStream.Free;
End;
End;
P.S. ©Drkb::03193 / Взято из http://forum.sources.ru
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|