![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогите распаковать gzip [D7, WinXP]
Вопрошающий © (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 байт выдергивается наличие доп заголовков/опций и их тоже нужно "вырезать"