用zlib压缩、解压缩流、判断是否压缩过了

海宏原创,用zlib压缩、解压缩流、判断是否压缩过了

//流操作:压缩流。源流不是全部压缩了,而是从当前position开始压缩
function CompressStream(oSource, oTarget:TStream; nCount:Int64=-1):integer;     //压缩流
var oZip:TCompressionStream;        oTmp:TMemoryStream;
    iBuf:Pointer;                   niSize:integer;                
begin
    result:=-1;
    try
      try
        niSize:=nCount;           
        if niSize<0 then niSize:=oSource.Size-oSource.Position; //默认为从当前position向后全部
        //if niSize=0 raise exception.Create('源流大小(默认为流体积-流当前位置)为0,非法。');
        oTarget.Position:=0;
        oTmp:=TMemoryStream.Create;
        //暂存
        getMem(iBuf, niSize+1);                       //获取缓冲内存
        oSource.read(iBuf^, niSize);                 //暂存入缓冲区
        oTmp.write(iBuf^, niSize);
        //压缩处理,最大压缩
        oZip:=zlib.TCompressionStream.Create(clMax, oTarget); //参数1是压缩比; 参数2是接收流
        oTmp.SaveToStream(oZip);                      //凡是传入的,都将被压缩
        freeAndNil(oZip);                             //压缩流 Free 后才真正完成压缩, 所以提前 Free
        //完成
        result:=oTarget.Size;
      finally
        if assigned(iBuf) then freeMem(iBuf);         //释放资源
        if assigned(oTmp) then oTmp.Free;
        if assigned(oZip) then oZip.Free;
      end;
    except
      on x:Exception do raise exception.Create('[CompressStream]压缩流出错(源流大小默认为流体积-流当前位置)!'#13+x.Message);
    end;
end;
//流操作:解压缩流
function DecompressStream(oSource, oTarget:TStream; nCount:Int64=-1):integer;   //解压缩流
var //oTmp:TMemoryStream;           oZip:TDeCompressionStream;
    iBuf, oBuf:Pointer;           n, niSize, noEstimate, noSize:Integer;
begin
    try
      try
        niSize:=nCount;           noEstimate:=0;
        if niSize<0 then niSize:=oSource.Size-oSource.Position; //默认为从当前position向后全部
        //if niSize=0 raise exception.Create('源流大小(默认为流体积-流当前位置)为0,非法。');
        //暂存
        getMem(iBuf, niSize+1);                       //获取缓冲内存
        oSource.read(iBuf^, niSize);                  //暂存入缓冲区
        //解压缩:直接解压缩缓冲区,可以返回大小;而用 TDeCompressionStream 必须指定大小
        zlib.DecompressBuf(iBuf, niSize, noEstimate, oBuf, noSize);
        oTarget.Position:=0;
        oTarget.Write(oBuf^, noSize);
        //完成
        result:=oTarget.Size;
      finally
        if assigned(iBuf) then freeMem(iBuf);         //释放资源
        if assigned(oBuf) then freeMem(oBuf);
      end;
    except
      on x:Exception do raise exception.Create('[DecompressStream]解压缩流出错(源流大小默认为流体积-流当前位置)!'#13+x.Message);
    end;
end;

//检查是否已经压缩过了
function TOleContainerStream.getIsZipped:Boolean;
const nZipSign=$DA78;     //直接打开文件发现,zlib压缩后的文件头,都是78DA开头
var nP:Integer;           nSign:Word;                 //smallInt
begin
    nSign:=self.size;
    if nSign<(sizeOf(Header)+sizeOf(nSign)) then
        result:=false
    else begin
        nP:=self.position;
        self.Position:=sizeOf(header);                //检查是否已经压缩过了
        self.Read(nSign, sizeOf(nSign));
        result:=nSign=nZipSign;
        self.position:=nP;
    end;
end;

 

你可能感兴趣的:(压缩,解压缩,integer,exception,function,header)