Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Помогите распаковать gzip [D7, WinXP]


Страницы:   1 2

Вопрошающий ©   (2007-10-28 02:00:00) 

нужно распаковать строку полученную при загрузке по хттп контента сжатого гзипом.
долго пытался что-то найти в поисковиках, но безуспешно.

пытался использовать функцию для распаковки строки сжатой zlib:
[code]
uses zlib;
...
function Unzlib(inpStr:string):string;
var
 OutBuf: Pointer;
 OutBytes: Integer;
 outstream:TStringStream;
begin
 OutStream:=TStringStream.create('');
 OutBuf := nil;
 try
   try
     DecompressBuf(pointer(InpStr), length(InpStr), 0, OutBuf, OutBytes);
     outStream.Write(OutBuf^, OutBytes);
   finally
     if OutBuf <> nil then FreeMem(OutBuf);
   end;
 outStream.Position := 0;
 Result:=outstream.DataString;
 finally
   OutStream.Free;
 end;
end;
[/code]

предварительно обрезавши первые 10 байт (сигнатура гзип), и добавивши 2 байта (сигнатура zlib), а также обрезавши последние 8 байт (CRC32+ISIZE) (RFC1952)
Но все равно не могу распаковать строку.
Возможно это из-за того что в zlib после самого сжатого потока должно быть 4 байта, где используется не CRC32, а ADLER32 (RFC1950). Но его естественно я никаким образом не смогу получить.

Может кто-нить подскажет, как все-таки распаковать данные, сжатые gzip, не используя сторонних компонентов?
Тем более что в WIN уже имеется библиотека gzip.dll, неплохо было бы ее задействовать, но вот ее описание не могу нигде найти.


Вопрошающий   (2007-11-01 22:11:00) [1]


> delete(s,1,pos(#13#10#13#10,s)+3);
> s2:=GZDecompressStr(s);


#13#10#13#10 ...
Это разделитель заголовка ответа хттп сервера от самих данных...
к гзип оно отношения не имеет...

А за ссылку спасибо... Попробовал. Отлично работает...


SuperHacker   (2007-11-01 20:29:00) [2]

Забыл дописать: вышеуказанный юнит для Delphi я взял здесь: http://www.base2ti.com/zlib.htm


SuperHacker   (2007-11-01 19:42:00) [3]


> нужно распаковать строку полученную при загрузке по хттп
> контента сжатого гзипом.

Я тоже долго с этим мучался, но потом решил проблему, используя zlib:

delete(s,1,pos(#13#10#13#10,s)+3);
s2:=GZDecompressStr(s);

В s лежит то, что сервер прислал, в s2 - раскодированный HTML.
В uses надо добавить ZlibExGz.


Вопрошающий   (2007-11-01 18:39:00) [4]


>        while true do
>        begin
>          r:=Read(Buf,SizeOf(Buf));
>          if r<=0 then Break;
>          Dest.WriteBuffer(Buf,r);
>        end;


Хм... Смысл мне не особо нравится... Но выглядит прилично... Да и работает...
Вобщем беру на вооружение этот вариант.

Спасибо!


Slym   (2007-11-01 04:23:00) [5]

Вопрошающий   (31.10.07 14:47) [13]
function GZipStringDecompress(const InputString:string):string;
var
 Source,Dest:TStringStream;
 Buf:array[byte] of byte;
 r:integer;
begin
 Dest:=TStringStream.Create('');
 try
   Source:=TStringStream.Create(InputString);
   try
     with TJclGZIPDecompressionStream.Create(Source) do
     try
       while true do
       begin
         r:=Read(Buf,SizeOf(Buf));
         if r<=0 then Break;
         Dest.WriteBuffer(Buf,r);
       end;
     finally
       Free;
     end;
   finally
     Source.Free;
   end;
   result:=Dest.DataString;
 finally
   Dest.Free;
 end;
end;


Вопрошающий   (2007-11-01 03:16:00) [6]

Вобщем путем предварительного определения размера данных путем вырезания последних 4-х байт из исходных данных получилось расжать гзип
разжимается нормально...

Но при попытке написать все это более менее прилично выяснилось что метод seek почему-то не работает во всех наследниках TStream, в частности даже в TStringStream... Вобщем какие-то странные вещи...пока не могу понять с чем это связано...


Вопрошающий   (2007-11-01 00:58:00) [7]


> ISize - это не в нашу тему?


Хм. Как-то я сразу до этого не додумался... получается что это уже один из вариантов решения вопроса... только вот он как-то выглядит череззаднепроходно... Но за неимением других вариантов возможно придется именно его и использовать.


Virgo_Style   (2007-10-31 22:45:00) [8]

Попытался вникнуть. М-да-а-а... давно я не брал в руки шашек...

Ansonsten wart mal ab. Gerade wird in der JCL an JclCompression gebaut.

Иначе были далеко однажды. Как раз строится в JCL в JclCompression.
(c) Prompt.

М-да.

Первое предложение мне больше кажется похожим на "Погоди-ка" или "Или подожди". Не пойму, это фигура речи или рекомендация по теме.
Вторая фраза вроде похожа на "Именно так устроен в JCL [юнит] JCLCompression", если так, то первая фраза - именно рекомендация.

p.s. Вот же делать мне нечего...

Жаль, слишком давно я работал с ZLib, уже не помню деталей, а ведь была подобная проблема...

Минуточку. > обрезавши последние 8 байт (CRC32+ISIZE)
ISize - это не в нашу тему?

Или еще мысль - нельзя ли разжимать постепенно, проверяя при этом position в сжатом потоке?

На этом я откланиваюсь, бо результаты ночных раздумий по утрам читать обычно или странно, или стыдно =)


Вопрошающий   (2007-10-31 20:08:00) [9]

Насчет первого я понял, что он обратил внимание на TStream, и поэтому, хоть он и правильно заметил, тем не менее его ответ не относится к существу вопроса.
Интерестно все-таки насколько результативен второй ответ?


Virgo_Style   (2007-10-31 19:17:00) [10]

Первый пишет, что TStream - абстрактный предок и его использовать нельзя, что пишет второй - я перевести не могу, жди знатоков)


Вопрошающий   (2007-10-31 17:12:00) [11]

Вот нашел в гугле:
http://www.delphipraxis.net/topic109876.html

У человека такая же проблема...
Правда не могу понять что ему там написали, ибо язык не понятный. на немецкий смахивает... Но я его не знаю...


Вопрошающий   (2007-10-31 14:53:00) [12]

Кстати, при выполнении:


> Read(Pointer(result)^, Size);


если я вместо SIZE указываю каку-ю нить константу заведомо меньшую того кол-ва данных, которое было сжато, то получаю кусок нужных данных, т.е. уже разжатых... Но вот проблема в определении их длины...


Вопрошающий   (2007-10-31 14:47:00) [13]


> сначала разожми, потом спрашивай размер... т.к. изначально
> размер без распаковки не известен


Хм... Вобщем пишу так:


function GZipStringDecompress(InputString:string):string;
var
 SourceStream:TStringStream;
begin
 SourceStream:=TStringStream.Create(InputString);
 try
   with TJclGZIPDecompressionStream.Create(SourceStream) do
     try
       SetString(result,nil,Size);
       Read(Pointer(result)^, Size);
     finally
       Free;
     end;
  finally
    SourceStream.Free;
  end;
end;


подскажите плиз что тут нужно изменить/добавить...


Slym   (2007-10-31 06:39:00) [14]

Вопрошающий   (31.10.07 6:16) [10]
seek is not an supported operation

сначала разожми, потом спрашивай размер... т.к. изначально размер без распаковки не известен


Вопрошающий   (2007-10-31 06:30:00) [15]

А при обращении к OriginalDataSize вылетает с "Stream read error"


Вопрошающий   (2007-10-31 06:16:00) [16]


> В Jedi: TJclGZIPDecompressionStream. Работает без проблем.


Скачал. Поробовал. Но проблемы все-таки есть...
Все вроде нормально расжимает, но страшно ругается при попытке обращения к свойству SIZE (выдает что "seek is not an supported operation").
и я уже не знаю как мне человеческим образом узнать размер распакованных данных...


Вопрошающий   (2007-10-30 16:45:00) [17]


> В Jedi: TJclGZIPDecompressionStream. Работает без проблем.


Я понимаю что гугль рулит, но все-таки огромнейшая просьба дать ссылку...
Так как в наше время как найти не трудно, трудно скачать...


Дмитрий Белькевич   (2007-10-30 02:20:00) [18]

В Jedi: TJclGZIPDecompressionStream. Работает без проблем.

В 7-ке стандартной идут 9-е либы. Только старые.


Вопрошающий   (2007-10-29 18:23:00) [19]


> Минимум 10 байт, на этом заголовок не кончается, из этих
> 10 байт выдергивается наличие доп заголовков/опций и их
> тоже нужно "вырезать"


Я исходил из того что там должен быть именно минимум...
Это контент переданный хттп-сервером, только пожатый гзипом для экономии трафика... И вроде в этих 10 байтах не было флагов присутствия дополнительных заголовков/опций.


> homm ©   (29.10.07 06:16) [5]
> > [0] Вопрошающий   (28.10.07 02:00)
> > пытался использовать функцию для распаковки строки сжатой
>
> > zlib:
> > Но все равно не могу распаковать строку.
>
> А должен был смочь?


Ну не знаю. Теоретически в гзипе используется метод сжатия zlib, поэтому я предположил, что должно сработать.
В инете находил шаманский метод по превращению данных сжатых zlib в gzip.
Там предлагается обрезать первых 2 байта (сигнатура zlib), вставивши вместо них 10 байтов сигнатуры gzip. Правда там имелся небольшой прокол связанный с контрольной суммой. Но автор написал, что это не особо важно, так как при распаковке такого гзип-файла стандартными средствами архиватор ругнется, но тем не менее распакует...


> Slym ©   (29.10.07 06:11) [4]
> в 10Indy тоже есть GZip декомпресор


Хм. Спасибо за подсказку... Поищу...
Кстати в стандартной поставке с 7 Дельфи какой Инди идет?


Slym   (2007-10-29 08:49:00) [20]

Вопрошающий   (28.10.07 2:00)
предварительно обрезавши первые 10 байт  (сигнатура гзип)

Минимум 10 байт, на этом заголовок не кончается, из этих 10 байт выдергивается наличие доп заголовков/опций и их тоже нужно "вырезать"


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо