zlib最快的压缩/解压写法

转自:http://delphi.ktop.com.tw/board.php?cid=31&fid=79&tid=32639

首先说明,这里不是横向比较zlib与别的引擎(rar,leo,powerarc...),是探索如何发挥zlib压缩/解压的最大效率。
先看看如下代码在效率上的差异:

var MS:TMemoryStream;
(1):
begin
    MS:=TMemoryStream.Create;
    MS.Size:=$400000;//4M
------------------------------------------------
(2):
var
    i:integer;
begin
    MS:=TMemoryStream.Create;
    for i:=1 to 1024 do MS.Size:=MS.Size+4096; 

你会发现,方法(1)只要1个毫秒,方法(2)却要20秒。
因此,如果把解压缩程序写成下面这样,会非常没有效率:

procedure ZlibDeCompress(instream,outStream:TStream);
var
    ACS:TDeCompressionStream;
    buf:array[1..4096] of byte;
    numread:integer;
begin
    inStream.Position:=0;
    ACS:=TDeCompressionStream.Create(inStream);
    try
    repeat
        numRead:=ACS.Read(buf,sizeof(buf));
        if numread>0 then outStream.Write(buf,numRead);
    until (numRead=0);
    finally
    ACS.Free;
    end;
end;

如果我们知道原始资料的大小,一次确定outStream.Size,效率就可以提高几十倍。方法很简单,我们可以在压缩时,把原始资料的Size写在压缩Stream的头部,如,写一个LongWord的大小,解压时就可以先读出Size,因此,最有效率的解压程序为:

procedure ZlibDecompressStream2(Source,Dest:TMemoryStream);
var
    zstream: TZStreamRec;
    SourceLen,DestLen:LongWord;
begin
    FillChar(zstream,SizeOf(TZStreamRec),0);
    SourceLen:=Source.Size;
    Source.Position:=0;
    Source.Read(DestLen,SizeOf(LongWord));
    Dest.Size:=DestLen;
    zstream.next_in:=Pointer(LongWord(Source.Memory)+SizeOf(LongWord));
    zstream.avail_in:=SourceLen-SizeOf(LongWord);
    zstream.next_out:=Dest.Memory;
    zstream.avail_out:=DestLen;
    ZDecompressCheck(InflateInit(zstream));
    try
    ZDecompressCheck(inflate(zstream,Z_NO_FLUSH));
    finally
    ZDecompressCheck(inflateEnd(zstream));
    end;
end;

用一个4M的文件试试,效率提高近70倍。
同样道理,在压缩的时候,如果能预先知道压缩后的大小,也能提高效率不少,但这似乎是不可能的,也不能盲目的给outStream.Size一个"足够大"的数值,只能按引擎的原理估算一个最接近的数值,zlib推荐的为:
((SourceLen+(SourceLen div 10)+12)+255) and not 255
因此,最有效率的压缩程序为:

procedure ZlibCompressStream2(Source,Dest:TMemoryStream;
    CompressLevel:TZCompressionLevel=zcFastest);
var
    zstream: TZStreamRec;
    SourceLen,DestLen:LongWord;
begin
    FillChar(zstream,SizeOf(TZStreamRec),0);
    SourceLen:=Source.Size;
    DestLen:=SizeOf(LongWord)+((SourceLen+(SourceLen div 10)+12)+255) and not 255;
    Dest.Size:=DestLen;
    Dest.Position:=0;
    Dest.Write(SourceLen,Sizeof(LongWord));
    zstream.next_in:=Source.Memory;
    zstream.avail_in:=SourceLen;
    zstream.next_out:=Pointer(LongWord(Dest.Memory)+SizeOf(LongWord));
    zstream.avail_out:=DestLen-SizeOf(longWord);
    ZCompressCheck(DeflateInit(zstream,ZLevels[CompressLevel]));
    try
    ZCompressCheck(deflate(zstream,Z_FINISH));
    finally
    ZCompressCheck(deflateEnd(zstream));
    end;
    Dest.Size:=zstream.total_out+SizeOf(LongWord);
end;

===============
久病成良医-多试

發表人 - mustapha.wang 於 2003/06/19 14:55:01


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值