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

Вниз

Проблема с 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]

Работающий пример уде раз пять здесь был :)
Тебе нужен пример павильного выковыривания сжатого куска из пдф :).

Извини, но никаким способом из непавильного "архива" правильные данные не получеш.


 
Samael6 ©   (2004-04-16 14:31) [41]

Спасибо за совет



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

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

Наверх




Память: 0.58 MB
Время: 0.035 c
6-1078989406
AlexS76
2004-03-11 10:16
2004.05.02
Как проверить доступен-ли удаленный компьютер по имени


3-1081082712
SergP
2004-04-04 16:45
2004.05.02
integer --> datetime. Как это сделать в запросе?


6-1078236954
-=zek=-
2004-03-02 17:15
2004.05.02
Пмогите пожалуйста с соединениемпо сети


3-1081100910
zerrow
2004-04-04 21:48
2004.05.02
помогите с нормализацией. что-то я запутался!


6-1078339833
ser_ega
2004-03-03 21:50
2004.05.02
Как узнать подключен ли я к инету?