软件开发者不免都要遇到压缩数据的问题!经常使用Delphi的朋友都知道它为我们提供了两个流类(TCompressionStream和TDecompressionStream)来完成数据的压缩和解压缩但美中不足的是该流在Delphi 的帮助中没有详细的说明使得它们在使用起来有一定得困难其实在Delphi系统中提供了这两个类的源代码和库保存在Delphi 光盘的\Info\Extras\Zlib\ Src和\Info\Extras\Zlib\Obj目录中(其中OBJ目录中保存的是库Src目录中保存的是源代码感兴趣的朋友可以看看)本人在使用的过程中对它们有了一定的了解
一 类的说明
基类 TCustomZlibStream类TCustomZlibStream 是类TCompressionStream和TDecompressionStream 类的基类它主要有一个属性 OnProgress在类进行压缩或解压缩的过程中会发生这个的事件 它的定义如下
Procedure OnProgress (Sender: TObject); dynamic;
压缩类TCompressionStream类TCompressionStream除了继承了基类的 OnProgress 属性外又增加了一个属性CompressionRate它的定义如下
Property CompressionRate: Single read GetCompressionRate;通过这个属性可以得到压缩比
它的几个个重要的方法定义如下
Constructor TCompressionStreamCreate (CompressionLevel: TCompressionLevel; Dest: TStream);
其中TcompressionLevel(压缩类型)它由如下几个定义
① clNone 不进行数据压缩
② clFastest进行快速压缩牺牲压缩效率
③ clDefault进行正常压缩
④ clMax 进行最大化压缩牺牲速度
Dest目的流用于存放压缩过的数据
Function TCompressionStreamWrite (const Buffer; Count: Longint): Longint;
其中Buffer需要压缩的数据
Count: 需要压缩的数据的字节数
函数返回写入流的字节数
压缩类TCompressionStream的数据只能是写入的如果试图从其内部读取数据将发生一个Error 异常需要压缩的数据通过方法 Write写入流中在写入的过程中就被压缩并保存在由构造函数提供的内存流(TmemoryStream)中同时触发 OnProcess 事件
解压缩类 TDecompressionStream :和压缩类TcompressionStream 相反它的数据是只能读出的如果试图往其内部写数据将发生一个Error 异常它的几个重要方法定义如下
构造函数Constructor Create(Source: TStream);
其中Source 是保存着压缩数据的流
Function Read(var Buffer; Count: Longint): Longint;
数据读出函数Buffer 存数据缓沖区
Count: 缓沖区的大小
函数返回读出的字节数
数据在读出的过程中数据被解压缩并触发 OnProcess 事件
二 类的使用
通过类TCompressionStream和TdecompressionStream的配合使用我们可以非常方便地完成数据的压缩和解压下面就是本人在编写屏幕拷贝程序中的使用例子
Procedure TClientFormGetScreen;
Var
SourceDCDestDC:HDC;
Bhandle:HBITMAP;
BitMap:TBitMap;
BmpStreamDeststream:TMemoryStream;
SourceStream:TCompressionStream;
Count:Integer;
Begin
SourceDC:=CreateDC(displaynil);
{得到屏幕的 DC}
DestDC:=CreateCompatibleDC(SourceDC);
{建立临时 DC}
Bhandle:=CreateCompatibleBitmap(SourceDCScreenWidth ScreenHeight);
{建立位图}
SelectObject(DestDCBhandle);
{选择位图DC}
BitBlt(DestDCScreenWidth ScreenHeightSourceDCSRCCOPY);
{拷贝整个屏幕}
BitMap:=TBitMapCreate;
BitMapHandle := Bhandle;
{保存屏幕位图到 BitMap中}
BmpStream:=TMemoryStreamCreate;
BitMapSaveToStream(BmpStream);
{建立位图数据的内存流}
count:=BmpStreamSize;
{保存位图的大小}
DestStream:=TMemoryStreamCreate;
{目标流保存压缩数据}
SourceStream:=TCompressionStreamCreate(clMax DestStream);
{构建压缩流采用最大化压缩并保存到目标流中}
try
BmpStreamSaveToStream(SourceStream);
{压缩位图流}
SourceStreamFree;
{完成压缩释放压缩流}
BmpStreamClear;
{清空原来位图流}
BmpStreamWriteBuffer(Count Sizeof(Count));
{将原来位图的大小保存到新的位图流中以便使用}
BmpStreamCopyFrom(DestStream );
{将压缩数据附加到新的位图流后面}
BmpStreamPosition := ;
NMStrmPostIt(BmpStream);
{发送位图流}
finally
DestStreamFree;
BmpStreamDestroy ;
BitMapDestroy;
DeleteDC(SourceDC);
ReleaseDC(BhandleSourceDC);
end;
{释放有关资源}
End;
该过程得到整个屏幕的图象拷贝并利用压缩流SourceStream和内存流 Deststream将位图压缩并重新把位图大小和压缩数据流保存到位图流中发送出去发送位图大小的目的是在解压前来确定需要的内存空间
procedure TServerFormNMStrmServMSG(Sender: TComponent;
const sFrom: String; strm: TStream);
Var
StreamStrDestStream:TMemoryStream;
SourceStream:TDecompressionStream;
count:Integer;
buffer:pointer;
begin
ScreenImagePictureBitmap:=nil;
If Strm Is TMemoryStream Then
StreamStr := Strm AS TMemoryStream
Else
Exit;
StreamStrPosition := ;
StreamStrReadBuffer(Count Sizeof(Count));
{得到位图的大小}
GetMem(BufferCount);
{申请数据空间}
DestStream := TMemoryStreamCreate;
SourceStream := TDecompressionStreamCreate(StreamStr);
{构建解压流压缩数据由StreamStr 流得到}
StatusBarSimpleText := 正在处理图象;
Try
SourceStreamReadBuffer(Buffer^Count);
{读出解压数据}
DestStreamWriteBuffer(Buffer^Count);
{保存到位图流中}
DestStreamPosition := ;
ScreenImagePictureBitmapLoadFromStream(DestStream);
{显示到屏幕上}
Finally
FreeMem(Buffer);
DestStreamDestroy;
SourceStreamDestroy;
End;
end;
该过程首先从得到的数据流中取得位图大小并申请内存空间然后建立解压流并将解压数据保存到位图流中然后显示到屏幕上