Форум: "Основная";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];
ВнизПроблема с ZLib Найти похожие ветки
← →
Samael6 © (2004-04-07 17:49) [0]Добрый день/вечер/утро!
Товарищи, если кто работал с ZLib, подскажите, плиз. Я пытаюсь распаковать блок данных содержащийся в PDF-файле и закодированный методом Flate. Все проходит чики-пуки, вот только выходной блок данных получается урезанным в конце. В чем может быть трабла? Может дело не в zlib, а в самом PDF, возможно ли такое и если нет, тогда что?
Заранее благодарен!
← →
Samael6 © (2004-04-08 17:54) [1]Интересно....неужели с ЗЛибом никто не работал?
Печально....
← →
mrcat © (2004-04-08 17:56) [2]с самим zlib"ом всё в порядке ... ищи проблему у себя ...
← →
Samael6 © (2004-04-08 17:59) [3]Вот процедура, которая реализует поставленную задачу. Что с ней не так?
procedure d_(const fn1,fn2:string);
var fs1, fs2:tfilestream;
ds: tdecompressionstream;
buf:array [1..1024] of char;
i: integer;
begin
fs1 := tfilestream.create(fn1,fmopenread);
fs2 := tfilestream.create(fn2,fmcreate);
try
try
ds := TDecompressionStream.Create(fs1);
ds.Position := 0;
repeat
i := ds.Read(buf,sizeof(buf));
if i <> 0 then
fs2.write(buf,i);
until(i <> sizeof(buf));
finally
ds.free;
end;
finally
fs1.free;
fs2.free;
end;
end;
← →
VMcL © (2004-04-08 18:22) [4]>>Samael6 c (08.04.04 17:59) [3]
У меня со zlib"ом была когда-то аналогичная проблема. Так и не разобрался, в чем дело: то ли у меня кривые руки, то ли нет, но решил с помощью увеличения размера буфера (у тебя `buf`).
P.S. OFF: Как думаешь, что будет, если случится exception на строке:fs2 := tfilestream.create(fn2,fmcreate);
?
← →
WebErr © (2004-04-08 18:27) [5]Удалено модератором
← →
Samael6 © (2004-04-08 18:45) [6]Не помогло.
← →
VMcL © (2004-04-08 19:05) [7]>>WebErr © (08.04.04 18:27) [5]
Никаких вопросов про запуздыривание иконок!
>>Samael6 © (08.04.04 18:45) [6]
Сколько поставил? Я ставил 1 МБ :)
← →
Reindeer Moss Eater © (2004-04-08 19:10) [8]Все очень просто.
При чтении из DecompressionStream надо указывать длину исходного несжатого файла, а не длину упакованного файла на который натравлен DecompressionStream.
Длину эту надо хранить где-то сбоку.
← →
VMcL © (2004-04-08 19:44) [9]>>Reindeer Moss Eater © (08.04.04 19:10) [8]
>Длину эту надо хранить где-то сбоку.
Во многих случаях это невозможно, например, если формат не свой.
← →
Mim1 (2004-04-08 21:09) [10]Reindeer Moss Eater © (08.04.04 19:10) [8]
Откуда вы это взяли?
← →
Mim1 (2004-04-08 21:18) [11]Samael6 © (08.04.04 17:59) [3]
procedure d_(const fn1,fn2:string);
var fs1, fs2:tfilestream;
ds: tdecompressionstream;
buf:array [1..1024] of byte;
i: integer;
begin
fs1 := tfilestream.create(fn1,fmopenread);
try
fs2 := tfilestream.create(fn2,fmcreate);
try
ds := TDecompressionStream.Create(fs1);
try
ds.Position := 0;
repeat
i := ds.Read(buf,sizeof(buf));
if i <> 0 then
fs2.write(buf,i);
until(i <> sizeof(buf));
finally
ds.free;
end;
finally
fs2.free;
end;
finally
fs1.free;
end;
end;
Тем не менее демается что ошибка в исходном файле а не в процедуре.
← →
VMcL © (2004-04-09 13:46) [12]>>Reindeer Moss Eater © (08.04.04 19:10) [8]
И вот еще: а если исходный файл стонадцать миллионов гигабайт весит, то где ж столько (виртуальной) памяти взять?
← →
Reindeer Moss Eater © (2004-04-09 14:10) [13]VMcL ©
Не распределяй память вообще. Создай поток для файла-результата и читай из потока DecompressionStream.
Mim1 (08.04.04 21:09) [10]
Reindeer Moss Eater © (08.04.04 19:10) [8]
Откуда вы это взяли?
Мама в детстве рассказывала на ночь.
VMcL © (08.04.04 19:44) [9]
>>Reindeer Moss Eater © (08.04.04 19:10) [8]
>Длину эту надо хранить где-то сбоку.
Во многих случаях это невозможно, например, если формат не свой.
Если формат не свой, то это не значит, что он не предусматривает некий заголовок архива, содержащий имена запакованных файлов, их длины и смещения относительно начала архива. Его (этот заголовок) и надо читать/писать при распаковке/создании архива не своего формата.
Возвращаясь к проблеме автора повторю:
По запакованному ZLib"ом потоку невозможно определить длину исходных данных.
А для правильного восстановления запакованного надо читать из DecompressionStream ровно столько, сколько туда было записано.
И естественно нельзя указать 0 в качестве длины (типа читать все до конца)
← →
VMcL © (2004-04-09 14:26) [14]>>Reindeer Moss Eater © (09.04.04 14:10) [13]
> Если формат не свой, то это не значит,
> что он не предусматривает некий заголовок архива
Вот Фома неверующий. Привести пример данных, формат которых не предусматривает заголовков, и тем не менее широко используется? И кто вообще говорил об архивах? Zlib не только в ZIP архивах используется.
← →
Reindeer Moss Eater © (2004-04-09 14:29) [15]Если какой-то формат не использует заголовков, то это означает, что ZLIB там не участвует.
← →
Polevi © (2004-04-09 14:48) [16]я использовал пару ф-ий CompressBuf и DecompressBuf
DecompressBuf сам выделяет память и сообщает о размере распакованных данных
← →
Reindeer Moss Eater © (2004-04-09 14:50) [17]Как DecompressBuf узнавал о размере незапакованных данных?
← →
VMcL © (2004-04-09 14:51) [18]>>Reindeer Moss Eater © (09.04.04 14:29) [15]
На что спорим? :))
← →
Reindeer Moss Eater © (2004-04-09 14:53) [19]VMcL ©
Сначала может о предмете спора мне расскажешь?
А то я в полном неведении
← →
Polevi © (2004-04-09 14:55) [20]procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
← →
Polevi © (2004-04-09 14:57) [21]PS
DecompressBuf это ф-ия из zlib, а не мной написанная
← →
Reindeer Moss Eater © (2004-04-09 14:57) [22]Polevi ©
То есть читать осторожно побайтно и до наступления исключения?
Тоже метод.
← →
VMcL © (2004-04-09 14:59) [23]>Reindeer Moss Eater © (09.04.04 14:53) [19]
>>VMcL © (09.04.04 14:26) [14]
>Привести пример данных, формат которых не предусматривает заголовков, и тем не менее широко используется?
>>Reindeer Moss Eater © (09.04.04 14:29) [15]
>Если какой-то формат не использует заголовков, то это означает, что ZLIB там не участвует.
На что спорим :), что есть формат, который не использует заголовков, но тем не менее упаковывается/распаковывается с помощью zlib?
← →
Reindeer Moss Eater © (2004-04-09 15:03) [24]VMcL ©
Спорить я не стану. Хотя бы по той причине, что возможно мы по разному понимаем что такое заголовок архива.
Алиса запаковала два файла ZLib"ом не исползуюя заголовок и отправила архив Бобу.
Как Боб восстанавливает имена файлов?
Ну хотя бы в общх чертах.
← →
Polevi © (2004-04-09 15:04) [25]>Reindeer Moss Eater © (09.04.04 14:57) [22]
procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer;
OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer);
{$ENDIF}
var
strm: TZStreamRec;
P: Pointer;
BufInc: Integer;
begin
FillChar(strm, sizeof(strm), 0);
strm.zalloc := zlibAllocMem;
strm.zfree := zlibFreeMem;
BufInc := (InBytes + 255) and not 255;
if OutEstimate = 0 then
OutBytes := BufInc
else
OutBytes := OutEstimate;
GetMem(OutBuf, OutBytes);
try
strm.next_in := InBuf;
strm.avail_in := InBytes;
strm.next_out := OutBuf;
strm.avail_out := OutBytes;
DCheck(inflateInit_(@strm, zlib_version, sizeof(strm)));
try
while inflate(strm, Z_FINISH) <> Z_STREAM_END do
begin
P := OutBuf;
Inc(OutBytes, BufInc);
ReallocMem(OutBuf, OutBytes);
strm.next_out := pBytef(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P)));
strm.avail_out := BufInc;
end;
finally
DCheck(inflateEnd(strm));
end;
ReallocMem(OutBuf, strm.total_out);
OutBytes := strm.total_out;
except
{$IFDEF Delphi16} {next line changed} {$ENDIF}
zlibFreeMem(NIL, OutBuf);
raise
end;
end;
← →
Reindeer Moss Eater © (2004-04-09 15:09) [26]Polevi ©
Все понятно. Сама библиотека не знает какого размера были исходные данные.
← →
VMcL © (2004-04-09 15:17) [27]>>Reindeer Moss Eater © (09.04.04 15:03) [24]
Повторю пост [14]:
И кто вообще говорил об архивах?
Ладно. Приведу все-таки пример. Программные модули для 1С 7.7 пакуются zlib"ом без заголовков. Далее запихиваются в стримы IStorage. Ну а данные IStorage сохраняются в файл конфигурации (*.md) или внешний отчет (*.ert).
← →
Reindeer Moss Eater © (2004-04-09 15:19) [28]И что это доказывает?
То что единственный блок информации запакован и помещен в объект - контейнер, который и выполняет роль заголовка, хранящего имена длины и еще бог знает что.
То что он не внутри упакованного стрима, а снаружи ничего не меняет.
← →
VMcL © (2004-04-09 15:35) [29]>>Reindeer Moss Eater © (09.04.04 15:19) [28]
AFAIK, нет в этих контейнерах (*.md, *.ert) данных о длине исходных потоков.
← →
Reindeer Moss Eater © (2004-04-09 15:39) [30]Формат *.md и *.ert документирован 1с или это догадка?
Если и нет там длин, значит они распаковываются по методу "читать по байту пока не исключение".
Классический компромис между экономией места и производительностью.
← →
VMcL © (2004-04-09 15:48) [31]>>Reindeer Moss Eater © (09.04.04 15:39) [30]
>Формат *.md и *.ert документирован 1с или это догадка?
Ага, дождешься от них документированности :(
Но это не догадка. Берем .md и/или .ert файл, натравливаем на него фаровский плагин DocFile и изучаем.
← →
Reindeer Moss Eater © (2004-04-09 15:50) [32]Ну вот.
Так и знал, что это догадка неутомимого исследователя.
← →
Mim1 (2004-04-09 19:18) [33]Reindeer Moss Eater © (09.04.04 14:10) [13]
Очень нехорошо отвечать заведомо неверно, опираясь не на справку или исходники а на рассказы мамы.
Распаковать такой файл можно и не зная размер сжатых данных воспользовавшись алгоритмом [3] или [11], у меня на этом алгаритме работает клиент сервра приложения (причем на двух платформах), естественно ошибок в нем нет.
Если по какой то причине распаковать таким алгоритмом данные не получается то ошибка на 99% в сжатых данных, например формат не верен и тп.
← →
Samael6 © (2004-04-12 15:39) [34]Да-а-а-а-а
Ребят, огромное спасибо за столь продолжительное обсуждение. Но я так и не увидел какого-то радикального решения поставленной задачи. Я туплю?
← →
Reindeer Moss Eater © (2004-04-12 15:48) [35]Mim1
Очень нехорошо отвечать заведомо неверно, опираясь не на справку или исходники а на рассказы мамы.
Перечитай ответы и найди у меня заведомо неверные посылы.
Найдешь - покажи.
← →
Samael6 © (2004-04-12 15:53) [36]Так что посоветуете? Вы говорили, что проблема возможно в самом файле. А как это можно проверить? Точнее как правильно вырезать из PDF этот блок и в чем там может быть проблема? Я обратил внимание, что описание блоков Flate там бывает различно, говорит ли это о том что и реализация упаковки/распаковки тоже может различаться? Если так, то помоему алес!
← →
Mim1 (2004-04-12 19:41) [37]Reindeer Moss Eater © (12.04.04 15:48) [35]
Не хочу провращать обсуждение в личныю перепалку, но тем не менее если вы просити дать ответ.
Перечитай ответы и найди у меня заведомо неверные посылы.
Найдешь - покажи.
Вот например.
Все очень просто.
При чтении из DecompressionStream надо указывать длину исходного несжатого файла, а не длину упакованного файла на который натравлен DecompressionStream.
Длину эту надо хранить где-то сбоку.
Дело в том что у меня есть пример из жизни. HTTP cервер сжимает ответ, естественно нигде не говорит "разбем несжатых данных 40 терабайт", и тем не менее я успешно распаковываю ответ методом аналогичным приведенному выше.
К сожалаень DecomperssBuf под каликсом не заработал :(, по этому я отказался от его использования.
Samael6 © (12.04.04 15:53) [36]
Ваш вопрос отличается от начального, рекоменжую завести отдельныю новую ветку.
← →
Samael6 © (2004-04-13 14:28) [38]
> Ваш вопрос отличается от начального, рекоменжую завести
> отдельныю новую ветку.
Да, немного. Но и по первому в принципе мало чего дельного сказали. Первый важнее, второй это просто следствие(возможное) из первого. Так что делать?
← →
Samael6 © (2004-04-15 13:51) [39]Ну как есть еще идеи? Может у кого работающий пример работы с ZLib есть?
← →
Mim1 (2004-04-15 20:45) [40]Работающий пример уде раз пять здесь был :)
Тебе нужен пример павильного выковыривания сжатого куска из пдф :).
Извини, но никаким способом из непавильного "архива" правильные данные не получеш.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.043 c