求ZLIB的解压算法(50分)

  • 主题发起人 主题发起人 吴剑明
  • 开始时间 开始时间

吴剑明

Unregistered / Unconfirmed
GUEST, unregistred user!
ZLIB的解压好奇怪,如果用COPYFROM解压,得先知道压缩前的文件大小,我试图在压缩时把
文件大小写到流里,结果在解压时无法读出来。:(
看了一些资料,有人用这种方法解压:
files := TMemoryStream.Create;
outs := TMemoryStream.Create;
files.LoadFromFile('c:/a.z');
deStream := TDeCompressionStream.Create(files);
size := deStream.Read(buf,1024);
while size >0 do
begin
outs.Write(buf,size);
size := deStream.Read(buf,1024); //循环到第三次,在这里死掉了。
end;
outs.SaveToFile('c:/b.txt');
怎么回事?
 
你又让我输掉了街头霸王zero.:(
 
像这样试一试:
var
Buffer: PChar;
Count: integer;
......
files.LoadFromFile('c:/a.z');
DeStream := TDeCompressionStream.Create(files);
Count := DeStream.ReadBuffer(Buffer^, files.size);
OutStream.WriteBuffer(Buffer^, Count);
OutStream.Position := 0;
OutStream.SaveToFile('c:/b.txt');
......
 
(2001-05-28 18:56:07) 可怜的鸡蛋
本来想可以预先把文件大小放到压缩文件里,解压时读出来,再COPYFROM,结果写是
写进去了,但是读不出来,压缩流的读法似乎和普通流的读法不大同,读出来的位置
不对,数值也就不对了。你看看应该怎么读

那就用一个笨一点的方法,压缩后保存,然后再直接往文件后面加字符串标明原文件
长度(不妨设字符串长度为8字节),可以用 textfile 的 append,甚至直接copy/b
总之,不要直接往 CompressionStream 里面加。
打开的时候可以用 TStringList,先读出长度:
strtoint(copy(s.Text, Length(s.Text) - 8, 8));
然后,把前面部分拷到一个 TMemoryStream,然后用上面我给的办法。

怎么样,这个办法够笨吧^_^ 其实只要你对速度要求不是特别高,就应该可以。

打完收工。
 
呵呵,我同意beta,以前在写socket传东西也有这个问题。所以,以后就直接写在第2个字节了
反正我觉得,“表示长度的那个数字不能被压缩”就对了,
 
对了,ZLIB的SOURCE在
http://vcl.vclxx.org/DELPHIGB/DEFAULT.HTM

本来是C++的,现在PASCAL的也有
 
ZLIB处理STREAM时有BUG。
ZLIB的压缩率没有LAH算法高。压缩时间也比LAH多一半。如果要求时间效率高的话可以试试。
 
多人接受答案了。
 
后退
顶部