海宏原创,用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;