Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.01.28;
Скачать: CL | DM;

Вниз

Модуль Compress.pas - распаковка ресурсов в файл   Найти похожие ветки 

 
koha ©   (2007-01-08 02:23) [0]

Вот на скорую руку модуль состряпал для запаковки / файлов на основе Zlib, так же для Распаковки Встроенных ресурсов в файл.
Кто, что подскажет для лучшей работы и исправления ляпусов ? А так вроде работает.

unit Compress;

interface

Uses Classes, Windows, SysUtils, ZLib;

Function CompressFile(InpFile: String; OutFile: String; N: Integer): boolean;
Function DecompressFile(InpFile: String; OutFile: String): boolean;
Function DecompressResToFile(ResName: String; FileName: String): Boolean;

Var
 INP_STRM, OUT_STRM : TFileStream;
 RES_STRM           : TResourceStream;
 COMPRESS_STRM      : TCompressionStream;
 DECOMPRESS_STRM    : TDecompressionStream;

implementation

Function CompressFile(InpFile: String; OutFile: String; N: Integer): boolean;
Var
 FBuffer: Array[0..1023] of char;
 ByteRaed: Integer;
Begin
try
 try
   INP_STRM := TFileStream.Create(InpFile,fmOpenRead);
   OUT_STRM := TFileStream.Create(OutFile,fmCreate);
   COMPRESS_STRM := TCompressionStream.Create(clMax,OUT_STRM);
   repeat
     ByteRaed := INP_STRM.Read(FBuffer,SizeOf(FBuffer));
     COMPRESS_STRM.Write(FBuffer,ByteRaed);
   until ByteRaed < 1024;
   Result:=True;
 finally
   COMPRESS_STRM.Free;
   INP_STRM.Free;
   OUT_STRM.Free;
   for ByteRaed:=0 to 1023 do FBuffer[ByteRaed]:=#0;
 end;
Except
 Result:=False;
 COMPRESS_STRM.Free;
 INP_STRM.Free;
 OUT_STRM.Free;
 for ByteRaed:=0 to 1023 do FBuffer[ByteRaed]:=#0;
end;

end;
Function DecompressFile(InpFile: String; OutFile: String): boolean;
Var
 Buffer: Array[0..1023] of char;
 ByteRaed: Integer;
Begin
try
 try
   INP_STRM := TFileStream.Create(InpFile,fmOpenRead);
   OUT_STRM := TFileStream.Create(OutFile,fmCreate);
   DECOMPRESS_STRM := TDecompressionStream.Create(OUT_STRM);
   repeat
     ByteRaed := INP_STRM.Read(Buffer,SizeOf(Buffer));
     DECOMPRESS_STRM.Write(Buffer,ByteRaed);
   until ByteRaed < 1024;
   Result:=True;
 finally
   DECOMPRESS_STRM.Free;
   INP_STRM.Free;
   OUT_STRM.Free;
   for ByteRaed:=0 to 1023 do Buffer[ByteRaed]:=#0;
 end;
Except
 Result:=False;
 DECOMPRESS_STRM.Free;
 INP_STRM.Free;
 OUT_STRM.Free;
 for ByteRaed:=0 to 1023 do Buffer[ByteRaed]:=#0;
end;

end;

Function DecompressResToFile(ResName: String; FileName: String): Boolean;
Var
 Buffer: Array[0..1023] of char;
 ByteRaed: Integer;
Begin
Try
 Try
   RES_STRM := TResourceStream.Create(HInstance,ResName,RT_RCDATA);
   OUT_STRM := TFileStream.Create(FileName,fmCreate);
   DECOMPRESS_STRM := TDecompressionStream.Create(RES_STRM);
   repeat
     ByteRaed:=DECOMPRESS_STRM.Read(Buffer,SizeOf(Buffer));
     OUT_STRM.Write(Buffer,ByteRaed);
   until ByteRaed < 1024;
   Result:=true;
 finally
   DECOMPRESS_STRM.Free;
   RES_STRM.Free;
   OUT_STRM.Free;
   for ByteRaed:=0 to 1023 do Buffer[ByteRaed]:=#0;
 end;
except
 DECOMPRESS_STRM.Free;
 RES_STRM.Free;
 OUT_STRM.Free;
 for ByteRaed:=0 to 1023 do Buffer[ByteRaed]:=#0;
 Result:=false;
end;
end;

end.


 
Anatoly Podgoretsky ©   (2007-01-08 02:28) [1]

> koha  (08.01.2007 02:23:00)  [0]

Глубоко не смотрел, но один ляпсус налицо, при ошибке будет попытка повторного освобождения объектов и как результат AV


 
Anatoly Podgoretsky ©   (2007-01-08 02:29) [2]

> koha  (08.01.2007 02:23:00)  [0]

Убрать из except данные строки

DECOMPRESS_STRM.Free;
RES_STRM.Free;
OUT_STRM.Free;
for ByteRaed:=0 to 1023 do Buffer[ByteRaed]:=#0;


 
Германн ©   (2007-01-08 02:43) [3]

Я тоже взглянул только мельком. Но моё имхо - неверное вложение блоков. Блок except нужно вкладывать в блок finally. А не наоборот. Тогда и не будет желания делать то, что согласно [2] нужно убрать.


 
Anatoly Podgoretsky ©   (2007-01-08 02:51) [4]

> Германн  (08.01.2007 02:43:03)  [3]

В данном случае без разницы, сначала отработает except, потом finally
Разница появляется когда после except должно продолжаться выполнение или блока или отдельных комманд, а вот дважды особождать не допустимо.


 
koha ©   (2007-01-08 02:54) [5]

- стоит ли делать это
  for ByteRaed:=0 to 1023 do Buffer[ByteRaed]:=#0;
 нужно ли освобождать или уничтожать вуфер и как правильно делать?

- И вот еще ляпус сам исправил функции

CompressFile(InpFile: String; OutFile: String; N: Integer): boolean;
  //..........
  if N > 3 then N:=3; //N это степень сжатия
  if N < 0 then N:=0;
  COMPRESS_STRM := TCompressionStream.Create(TCompressionLevel(N),OUT_STRM);
  //.............


 
Джо ©   (2007-01-08 02:57) [6]

> [5] koha ©   (08.01.07 02:54)
> - стоит ли делать это
>  for ByteRaed:=0 to 1023 do Buffer[ByteRaed]:=#0;

Нет, это совершенно бессмысленно.


 
Anatoly Podgoretsky ©   (2007-01-08 02:58) [7]

> koha  (08.01.2007 02:54:05)  [5]

> - стоит ли делать это

Не стоит, после выхода из процедуры буфер прекращает свое существование


 
koha ©   (2007-01-08 03:13) [8]

И в случае критической ошибки будет ли  выполнено обязательно
 try finally //.....  end;


 
Anatoly Podgoretsky ©   (2007-01-08 03:24) [9]

> koha  (08.01.2007 03:13:08)  [8]

try finally выполнится всегда, как бы не прерывалось выполнение блока. Можно даже делать exit из процедуры в любом месте. except будет выполнен при исключение, затем будет выполнен finally для твоего кода.


 
Германн ©   (2007-01-08 03:24) [10]


> Anatoly Podgoretsky ©   (08.01.07 02:51) [4]
>
> > Германн  (08.01.2007 02:43:03)  [3]
>
> В данном случае без разницы, сначала отработает except,
> потом finally

Но читается по разному, пока не поймёшь суть.


 
Anatoly Podgoretsky ©   (2007-01-08 03:27) [11]

> Германн  (08.01.2007 03:24:10)  [10]

Конечно я бы не стал так писать, это же голову надо влево наклонять
Более понятно и естественно писать так.

try
  try
  except
  end
finally
end


 
Германн ©   (2007-01-08 03:48) [12]


> Anatoly Podgoretsky ©   (08.01.07 03:27) [11]
>
> > Германн  (08.01.2007 03:24:10)  [10]
>
> Конечно я бы не стал так писать, это же голову надо влево
> наклонять
> Более понятно и естественно писать так.
>
> try
>   try
>   except
>   end
> finally
> end
>

Ну и я про тоже сказал в [3].


 
koha ©   (2007-01-08 04:03) [13]

Вот еще дописал к этому модулю одну функцию уже с учетом всех высказываний выше, которая извлекает в файл сжатый ресур по ResId.

Function DecompressResIdToFile(ResId: Integer; OutFileName: String): Boolean;
Var
 Buffer: Array[0..1023] of char;
 ByteRaed: Integer;
begin
Try
 try
   RES_STRM := TResourceStream.CreateFromID(HInstance,ResId,RT_RCDATA);
   OUT_STRM := TFileStream.Create(OutFileName,fmCreate);
   DECOMPRESS_STRM := TDecompressionStream.Create(OUT_STRM);
   repeat
     ByteRaed := INP_STRM.Read(Buffer,SizeOf(Buffer));
     DECOMPRESS_STRM.Write(Buffer,ByteRaed);
   until ByteRaed < 1024;
   Result:=True;
 except
   Result:=false;
 end;
finally
 DECOMPRESS_STRM.Free;
 RES_STRM.Free;
 OUT_STRM.Free;
end;
end;


 
Джо ©   (2007-01-08 04:07) [14]

> except
>   Result:=false;
> end;

Не стоит так делать, ИМХО. Ты маскируешь ошибку, причем скрываешь ее причину, выдывая взамен малоинформативный False.


 
Германн ©   (2007-01-08 04:21) [15]

Добавлю к
> Джо ©   (08.01.07 04:07) [14]
.
Уже встречался с подобным. Геморрой неимоверный!  Есть у меня пример, который работает именно так, но у меня "особые" условия!


 
koha ©   (2007-01-08 04:41) [16]

> Джо ©   (08.01.07 04:07) [14]
> Германн ©   (08.01.07 04:21) [15]

- Тогда закономерный вопрос : как проконтролировать выполнение и не выполение функции?


 
Джо ©   (2007-01-08 04:56) [17]

> [16] koha ©   (08.01.07 04:41)
> > Джо ©   (08.01.07 04:07) [14]
> > Германн ©   (08.01.07 04:21) [15]
>
> - Тогда закономерный вопрос : как проконтролировать выполнение
> и не выполение функции?

Если не произошло исключения, значит процедура выполнилась успешно.


 
koha ©   (2007-01-08 06:35) [18]

> Если не произошло исключения, значит процедура выполнилась успешно

- вот именно этой процедуре, извеняюсь, т.е. функции можетбыть и вовсе нестоит быть функцией?


 
Джо ©   (2007-01-08 06:39) [19]

> [18] koha ©   (08.01.07 06:35)
> > Если не произошло исключения, значит процедура выполнилась
> успешно
>
> - вот именно этой процедуре, извеняюсь, т.е. функции можетбыть
> и вовсе нестоит быть функцией?

Может, и не стоит. По крайней мере, в таком варианте, когда на любую ошибку возвращается просто False, а не причина ошибки. Особого смысла в этом нет.


 
app ©   (2007-01-08 07:07) [20]


> Тогда закономерный вопрос : как проконтролировать выполнение
> и не выполение функции?

Убери совсем except и далее смотри [17] и далее.


 
koha ©   (2007-01-08 07:19) [21]

> app ©   (08.01.07 07:07) [20]
> Убери совсем except и далее смотри [17] и далее.

- в таком случае предлагается наверное это:
try
 Myfunction();
except //....... end;


 
Anatoly Podgoretsky ©   (2007-01-08 07:29) [22]

> koha  (08.01.2007 07:19:21)  [21]

Именно это тебе и предлагали, это более гибко.


 
koha ©   (2007-01-08 07:56) [23]

- в этом немного разобрался ведь по сути теперь особой разницы не видать как обработку ошибок вести или внутри функции или снаружи, я думаю это наверное зависить будет от того в каком месте программы функцию  использовать. Меня так устраивает и такой вариант:
function();
 try
   //..........
   result:=true;
 except MessageDlg(); end;
  //........
end;

Вот еще осталось написать пару функций, довольно актуальных, которые при помощи Zlib сжимали и расжимали данные перед и после отправки пакетов по сети.
Дописать утилиту, которая будет готовить из файлов сжатые ресурсы и выложить на свой сайт и будет все шоколаде шоколаде.



Страницы: 1 вся ветка

Текущий архив: 2007.01.28;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.046 c
15-1168344143
Какондекалло
2007-01-09 15:02
2007.01.28
Централизованное тестирование! Пример


15-1168591625
Desdechado
2007-01-12 11:47
2007.01.28
Подать в суд на суд


15-1168090815
Lhbd
2007-01-06 16:40
2007.01.28
Выдрать драйвер...


5-1147125189
Константинов
2006-05-09 01:53
2007.01.28
Свойства - события


15-1167986950
Chuk &amp; Gek
2007-01-05 11:49
2007.01.28
ГМТ,