DELPHI 通过ZLib来压缩文件夹

unit Unit1;

interface

uses
ZLib,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls; const
cBufferSize = $;
cIdent: string[] = 'zsf';
cVersion = $;
cErrorIdent = -;
cErrorVersion = -; type
TFileHead = packed record
rIdent: string[]; //标识
rVersion: Byte; //版本
end; type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
function StrLeft(const mStr: string; mDelimiter: string): string; function StrRight(const mStr: string; mDelimiter: string): string; function FileCompression(mFileName: TFileName; mStream: TStream): Integer; function FileDecompression(mFileName: TFileName; mStream: TStream): Integer; function DirectoryCompression(mDirectory, mFileName: TFileName): Integer; function DirectoryDecompression(mDirectory, mFileName: TFileName): Integer; { Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.dfm} function TForm1.DirectoryCompression(mDirectory,
mFileName: TFileName): Integer;
var
vFileInfo: TStrings;
vFileInfoSize: Integer;
vFileInfoBuffer: PChar;
vFileHead: TFileHead; vMemoryStream: TMemoryStream;
vFileStream: TFileStream; procedure pAppendFile(mSubFile: TFileName);
begin
vFileInfo.Append(Format('%s|%d',
[StringReplace(mSubFile, mDirectory + '\', '', [rfReplaceAll, rfIgnoreCase]),
FileCompression(mSubFile, vMemoryStream)]));
Inc(Result);
end; procedure pSearchFile(mPath: TFileName);
var
vSearchRec: TSearchRec;
K: Integer;
begin
K := FindFirst(mPath + '\*.*', faAnyFile, vSearchRec);
while K = do
begin
if (vSearchRec.Attr and faDirectory > ) and
(Pos(vSearchRec.Name, '..') = ) then
pSearchFile(mPath + '\' + vSearchRec.Name)
else if Pos(vSearchRec.Name, '..') = then
pAppendFile(mPath + '\' + vSearchRec.Name);
K := FindNext(vSearchRec);
end;
FindClose(vSearchRec);
end;
begin
Result := ;
if not DirectoryExists(mDirectory) then
Exit;
vFileInfo := TStringList.Create;
vMemoryStream := TMemoryStream.Create;
mDirectory := ExcludeTrailingPathDelimiter(mDirectory); vFileStream := TFileStream.Create(mFileName, fmCreate or fmShareDenyWrite);
try
pSearchFile(mDirectory);
vFileInfoBuffer := vFileInfo.GetText;
vFileInfoSize := StrLen(vFileInfoBuffer); { DONE -oZswang -c添加 : 写入头文件信息 }
vFileHead.rIdent := cIdent;
vFileHead.rVersion := cVersion;
vFileStream.Write(vFileHead, SizeOf(vFileHead)); vFileStream.Write(vFileInfoSize, SizeOf(vFileInfoSize));
vFileStream.Write(vFileInfoBuffer^, vFileInfoSize);
vMemoryStream.Position := ;
vFileStream.CopyFrom(vMemoryStream, vMemoryStream.Size);
finally
vFileInfo.Free;
vMemoryStream.Free;
vFileStream.Free;
end;
end; function TForm1.FileCompression(mFileName: TFileName;
mStream: TStream): Integer;
var
vFileStream: TFileStream;
vBuffer: array[..cBufferSize]of Char;
vPosition: Integer;
I: Integer;
begin
Result := -;
if not FileExists(mFileName) then Exit;
if not Assigned(mStream) then Exit;
vPosition := mStream.Position;
vFileStream := TFileStream.Create(mFileName, fmOpenRead or fmShareDenyNone);
with TCompressionStream.Create(clMax, mStream) do try
for I := to vFileStream.Size div cBufferSize do begin
vFileStream.Read(vBuffer, cBufferSize);
Write(vBuffer, cBufferSize);
end;
I := vFileStream.Size mod cBufferSize;
if I > then begin
vFileStream.Read(vBuffer, I);
Write(vBuffer, I);
end;
finally
Free;
vFileStream.Free;
end;
Result := mStream.Size - vPosition; //增量
end; procedure TForm1.Button1Click(Sender: TObject);
var
i : Integer;
begin
try i:=DirectoryCompression('E:\Ark\ProjectDebug\PublicBill\Server\QueryOut\Log','E:\Ark\ProjectDebug\PublicBill\Server\QueryOut\log.rar');
except
Application.MessageBox('',PChar(inttostr(i)),);
end;
end; function TForm1.DirectoryDecompression(mDirectory,
mFileName: TFileName): Integer;
var
vFileInfo: TStrings;
vFileInfoSize: Integer;
vFileHead: TFileHead; vMemoryStream: TMemoryStream;
vFileStream: TFileStream;
I: Integer;
begin
Result := ;
if not FileExists(mFileName) then
Exit;
vFileInfo := TStringList.Create;
vMemoryStream := TMemoryStream.Create;
mDirectory := ExcludeTrailingPathDelimiter(mDirectory);
vFileStream := TFileStream.Create(mFileName, fmOpenRead or fmShareDenyNone);
try
if vFileStream.Size < SizeOf(vFileHead) then Exit;
{ DONE -oZswang -c添加 : 读取头文件信息 }
vFileStream.Read(vFileHead, SizeOf(vFileHead));
if vFileHead.rIdent <> cIdent then Result := cErrorIdent;
if vFileHead.rVersion <> cVersion then Result := cErrorVersion;
if Result <> then Exit; vFileStream.Read(vFileInfoSize, SizeOf(vFileInfoSize));
vMemoryStream.CopyFrom(vFileStream, vFileInfoSize);
vMemoryStream.Position := ;
vFileInfo.LoadFromStream(vMemoryStream); for I := to vFileInfo.Count - do
begin
vMemoryStream.Clear;
vMemoryStream.CopyFrom(vFileStream,
StrToIntDef(StrRight(vFileInfo[I], '|'), ));
vMemoryStream.Position := ;
FileDecompression(mDirectory + '\' + StrLeft(vFileInfo[I], '|'),
vMemoryStream);
end;
Result := vFileInfo.Count;
finally
vFileInfo.Free;
vMemoryStream.Free;
vFileStream.Free;
end;
end; function TForm1.StrLeft(const mStr: string; mDelimiter: string): string;
begin
Result := Copy(mStr, , Pos(mDelimiter, mStr) - );
end; function TForm1.StrRight(const mStr: string; mDelimiter: string): string;
begin
if Pos(mDelimiter, mStr) > then
Result := Copy(mStr, Pos(mDelimiter, mStr) + Length(mDelimiter), MaxInt)
else
Result := '';
end; function TForm1.FileDecompression(mFileName: TFileName;
mStream: TStream): Integer;
var
vFileStream: TFileStream;
vBuffer: array[..cBufferSize]of Char;
I: Integer;
begin
Result := -;
if not Assigned(mStream) then Exit;
ForceDirectories(ExtractFilePath(mFileName)); //创建目录 vFileStream := TFileStream.Create(mFileName, fmCreate or fmShareDenyWrite); with TDecompressionStream.Create(mStream) do
try
repeat
I := Read(vBuffer, cBufferSize);
vFileStream.Write(vBuffer, I);
until I = ;
Result := vFileStream.Size;
finally
Free;
vFileStream.Free;
end;
end; procedure TForm1.Button2Click(Sender: TObject);
var
i : Integer;
begin
try
i:=DirectoryDecompression('E:\Ark\ProjectDebug\PublicBill\Server\QueryOut\Log2','E:\Ark\ProjectDebug\PublicBill\Server\QueryOut\log.rar');
except
Application.MessageBox('',PChar(inttostr(i)),);
end; end; end.

Base64编码解码及ZLib压缩解压

最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结:
一.Base64编码/解码
  一般用到的是Delphi自带的单元EncdDecd,当然还有第三方提供的单元或控件,其中我所接触到的认为比较好的有Indy的TIdMimeEncode / TIdMimeDecode组件,以及RjMime单元.
  在这里主要想讲讲如何才能获得最好的编码/解码性能,EncdDecd提供了EncodeStream/DecodeString, EncodeString/DecodeString两对函数,如果你使用EncodeString/DecodeString,这没有什麽可争议,效率是死的,如果你使用了EncodeStream/DecodeStream,这里面可大有文章了. 先来看看两个函数的声明:
procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(Input, Output: TStream);
  很明了, 两个参数,都为TStream, TStream是抽象类, 其派生类主要有TMomoryStream,TStringStream,TFileStream等,都可以作为参数传递进去,对於Input参数,无论TMemoryStream, TStringStream, TFileStream都不会影响性能,但是对於Output参数,由於压缩的结果是写住OutputStream,因此压缩过程中不断地执行TStream的Write方法,如果是TMemoryStream,那效率真是太糟糕了,我作过测试,编码一个5M多的文件,要十几秒钟!但如果是TStringStream呢,只要0.2~0.3秒! 这究竟是为什麽呢,因为TMemoryStream里不断调用Write方法的结果是,不断地向Windows要求分配内存!从而导致性能下降!而TStringStream和TFileStream则没有这个问题. 因此,在这里极力向朋友们建议,Output参数最好不用TMemoryStream.
  不过不要紧,你一定要用的话,也是有方法解决性能下降这个问题的! 因为效率下降的原因是不断的申请内存空间,我们可以从这个方向首手,能不能一次性给它分配好内存空间呢,如果我们事先能确定编码或解码后的数据大小(字节数),那麽这是可行的. 问题的关键就是如何确定这个编码或解码后的字节数了. 对於EncdDecd,我可以给出这个计算方法:
  (1)假设编码前的字节数为X,那麽编码后的字节数为 (X + 2) div 3 * 4. 不过,要对EncdDecd进行相应的修改,找到这一小段:
   if K > 75 then     
   begin
    BufPtr[0] := #$0D;
    BufPtr[1] := #$0A;
    Inc(BufPtr, 2);
    K := 0;
   end;
  将其注释掉, 因为这其实是没什麽用的,只是用来对编码后的字符串分行的~,我们可以注释后将单元另存为EncdDecdEx,以后就使用它了!!!
  (2)假设解码前的字节数是X,那麽解码后的字节数约为 (X + 3) div 4 * 3
*****注:与编码不同的是,解码的字节数不是确定的,差值在0~2之间.
  这样我们就可以在编码/解码前对Output参数的TMemoryStream事先设置缓冲区大小了....
 

 uses
  encddecdEx;
 var
  Input,Output:TMemoryStream;
 begin
  Input:=TMemoryStream.Create;
  try
   Input.LoadFromFile('c:\aaa.txt');
   Output:=TMemoryStream.Create;
   try
    Output.Size:=(Input.Size + ) div * ;
    EncodeStream(Input,Output);
   finally
    Output.Free;
   end;
  finally
   Input.Free;
  end;
 end;

 OK! 大功告成!!! 大家有兴趣可以测试一下,加不加Output.Size:=(Input.Size + 2) div 3 * 4这一句的不同效果~
二.ZLib压缩/解压
  在一些分布式系统中,特别是Internet分布式系统,由於网络带宽所限,我们需要对传输的大流量数据进行压缩,以减轻网络的负担,加快程序运行速度,一般用到的压缩/解压方法是使用ZLib单元. ZLib单元主要提供了两个类:TCompressionStream和TDeCompressionStream. 这两个类分别处理压缩和解压缩. 使用方法可以查阅相关的资料. 在这里提供两个过程,再对压缩时的参数作些比较:

uses
 ZLib;
procedure Zip(Input,Output:TStream;Compress:Boolean);
const
 MAXBUFSIZE= * ;  //16 KB
var
 CS:TCompressionStream;
 DS:TDecompressionStream;
 Buf:array[..MAXBUFSIZE-] of Byte;
 BufSize:Integer;
begin
  if Assigned(Input) and Assigned(Output) then
 begin
  if Compress then
  begin
   CS:=TCompressionStream.Create(clDefault,Output);
   try
    CS.CopyFrom(Input,); //从开始处复制
   finally
    CS.Free;
   end;
  end else
  begin
   DS:=TDecompressionStream.Create(Input);
   try
    BufSize:=DS.Read(Buf,MAXBUFSIZE);
    while BufSize> do
    begin
     Output.Write(Buf,BufSize);
     BufSize:=DS.Read(Buf,MAXBUFSIZE);
    end;
   finally
    DS.Free;
   end;
  end;
 end;
end;
function Zip(Input:string;Compress:Boolean):string;
var
 InputStream,OutputStream:TStringStream;
begin
 if Input='' then Exit;
 InputStream:=TStringStream.Create(Input);
 try
  OutputStream:=TStringStream.Create('');
  try
   Zip(InputStream,OutputStream,Compress);
   Result:=OutputStream.DataString;
  finally
   OutputStream.Free;
  end;
 finally
  InputStream.Free;
 end;
end;

  以上两个方法是两个名称一样,参数不同的过程. 第一个是对流进行压缩/解压,Input,Output分别是压缩/解压前的流与压缩/解压后的流. 第二个是对字符串进行压缩/解压. 两个过程都有Compress参数,这个参数用来决定进行压缩操作还是解压操作: True--压缩; false--解压.
  在第一个过程中,有这样一句:
  CS:=TCompressionStream.Create(clDefault,Output);
  这是在建立压缩类以对流进行压缩, 这里面有个参数clDefault,当然还有其它的选项:clNone, clFastest, clDefault, clMax;
clNone与clFastest就不讨论了,因为不能获得良好的压缩效果,在这里想讨论clDeafult与clMax哪一个好点,我作了一些测试,测试数据如下:

        源文件大小  压缩所用时间   压缩后文件大小
 clDefault   2.71M     ~1.4s      ~937K
         5.10M     ~2.8s      ~1.77M
 clMax     2.71M     ~2.5s      ~934K
         5.10M     ~4.7s      ~1.77M
  由这些数据可以看出,clDefault参数与clMax参数,压缩率已经非常接近了,但是所用的时间却相差了近一倍! 也就是说,差不多的压缩效率,clDefault参数比clMax参数节省了一半的时间! 因此,建议大家使用参数clDefault,这是压缩效率比较好的参数.

三. 何对MIDAS封包进行压缩.
  我们知道,MIDAS封包外在类型是OleVariant,其内部格式没有对外公开! 经过我的一些测试,该封包是以varByte为基础类型的VarArray数组.
因此,我们可以将其转换成string类型再进行压缩,至於压缩后是以string传输还是转换回VarByte array类型,就由个人决定了. 下面的函数完成将MIDAS数据包转换成string类型.

function UnpackMIDAS(vData:OleVariant):string;
var
 P:Pointer;
 Size:Integer;
begin
 if not VarIsArray(vData) then Exit;
 Size:=VarArrayHighBound(vData,)-VarArrayLowBound(vData,)+;
 P:=VarArrayLock(vData);
 try
  SetLength(Result,Size);
  Move(P^,Result[],Size);
 finally
  VarArrayUnLock(vData);
 end;
end;

假设以下为MIDAS服务器或COM+对象一个方法.

function TDeptCoor.GetDeptData: OleVariant;
var
 Command:WideString;
 Options:TGetRecordOptions;
 RecsOut:Integer;
 Params,OwnerData:OleVariant;
begin
 try
  Command:='SELECT DeptID,DeptNo,DeptName,MasterID FROM Department ORDER BY DeptNo';
  Options:=[grReset,grMetaData];
  Result:=FCommTDM.AS_GetRecords('CommDsp',-,RecsOut,Byte(Options),Command,Params,OwnerData);
  Result:=UnpackMIDAS(Result);  //将MIDAS封包转换成string类型
  Result:=Zip(Result,True);      //进行压缩,再将压缩后结果转回.
  SetComplete;
 except
  SetAbort;
  raise;
 end;
end;

客户端只要压压缩后就可以使用了:

procedure TForm1.Button1Click(sender:TObject);
var
 vData:string;
begin
 vData:=DeptCoor.GetDeptData;
 vData:=Zip(vData,False);     //解压
 ClientDataSet1.XMLData:=vData;  //注意,这里用的是XMLData,不是Data,否则会报错!!!
end;

        
四. SOAP系统中压缩后编码:
 在SOAP系统中,由於二进制数据不能直接传递,需要进行Base64编码, 我们可以在数据传递前先压缩/Base64编码,接收后再Base64解码/解压缩.
同样,也给出两个函数,来分别完成这两个过程

function SoapPacket(const Input:string):string; 
var
 InputStream,OutputStream:TStringStream;
begin
 InputStream:=TStringStream.Create(Input);
 try
  OutputStream:=TStringStream.Create('');
  try
   Zip(InputStream,OutputStream,True);
   InputStream.Size:=;
   OutputStream.Position:=;  //很重要!!!
   EncodeStream(OutputStream,InputStream);
   Result:=InputStream.DataString;
  finally
   OutputStream.Free;
  end;
 finally
  InputStream.Free;
 end;
end;
function SoapUnpack(const Input:string):string;
var
 InputStream,OutputStream:TStringStream;
begin
 InputStream:=TStringStream.Create(Input);
 try
  OutputStream:=TStringStream.Create('');
  try
   DecodeStream(InputStream,OutputStream);
   InputStream.Size:=;
   OutputStream.Position:=; //很重要!!!
   Zip(OutputStream,InputStream,False);
   Result:=InputStream.DataString;
  finally
   OutputStream.Free;
  end;
 finally
  InputStream.Free;
 end;
end;

Delphi使用Zlib

uses
zlib;
//将Src使用Zlib压缩后存入Dst当中
procedure PackStream(const Src:TStream; Dst:TStream);
var
CompStream: TCompressionStream;
begin
//增加“断言”以防止输入参数有误
Assert(Src <> Nil);
Assert(Dst <> Nil);
CompStream := TCompressionStream.Create(clDefault,Dst);
try
//将源数据的偏移转到首部
Src.Seek(,soFromBeginning);
//使用CopyFrom将源数据输入到压缩流,以实现压缩
CompStream.CopyFrom(Src,);
finally
CompStream.Free;
end;
end;
//将以zlib压缩的Src解压缩后存入Dst当中
procedure UnpackStream(const Src:TStream; Dst:TStream);
var
DecompStream: TDecompressionStream;
NewSize: Int64;
begin
//增加“断言”以防止输入参数有误
Assert(Src <> Nil);
Assert(Dst <> Nil);
DecompStream:= TDecompressionStream.Create(Src);
try
//将源数据的偏移转到首部
NewSize := Src.Seek(, soFromEnd);
Src.Seek(, soFromBeginning);
//使用CopyFrom将源数据输入到解压缩流,以实现解压缩
//并得到实际解压缩后的数据大小(NewSize)
//内部会使用AllocMem(System单元定义)对Dst进行内存重新分配
//所以,Dst的内存管理必须兼容AllocMem进行内存分配
NewSize := Dst.CopyFrom(DecompStream,NewSize);
//重新设置Dst的实际大小(已经在解压缩过程当中进行重新分配)
Dst.Size := NewSize;
finally
DecompStream.Free;
end;
end;
//测试代码
procedure Test;
var
SrcStream,PackedStream,UnpackedStream:TMemoryStream;
begin
SrcStream := TMemoryStream.Create;
try
SrcStream.LoadFromFile('c:\test.xml');
PackedStream := TMemoryStream.Create;
try
//压缩
PackStream(SrcStream, PackedStream);
PackedStream.Seek(, soFromBeginning);
PackedStream.SaveToFile('c:\test_xml.pk');
UnpackedStream := TMemoryStream.Create;
try
//解压缩
UnpackStream(PackedStream, UnpackedStream);
UnpackedStream.Seek(, soFromBeginning);
UnpackedStream.SaveToFile('c:\test_xml.xml');
finally
UnpackedStream.Free;
end;
finally
PackedStream.Free;
end;
finally
SrcStream.Free;
end;
end;

Delphi使用Zlib示例代码

uses  zlib; 

//将Src使用Zlib压缩后存入Dst当中
procedure PackStream(const Src:TStream; Dst:TStream);
var
CompStream: TCompressionStream;
begin
//增加“断言”以防止输入参数有误
Assert(Src <> Nil);
Assert(Dst <> Nil); CompStream := TCompressionStream.Create(clDefault,Dst);
try
//将源数据的偏移转到首部
Src.Seek(,soFromBeginning);
//使用CopyFrom将源数据输入到压缩流,以实现压缩
CompStream.CopyFrom(Src,);
finally
CompStream.Free;
end;
end; //将以zlib压缩的Src解压缩后存入Dst当中
procedure UnpackStream(const Src:TStream; Dst:TStream);
var
DecompStream: TDecompressionStream;
NewSize: Int64;
begin
//增加“断言”以防止输入参数有误
Assert(Src <> Nil);
Assert(Dst <> Nil); DecompStream:= TDecompressionStream.Create(Src);
try
//将源数据的偏移转到首部
NewSize := Src.Seek(, soFromEnd);
Src.Seek(, soFromBeginning);
//使用CopyFrom将源数据输入到解压缩流,以实现解压缩
//并得到实际解压缩后的数据大小(NewSize)
//内部会使用AllocMem(System单元定义)对Dst进行内存重新分配
//所以,Dst的内存管理必须兼容AllocMem进行内存分配
NewSize := Dst.CopyFrom(DecompStream,NewSize);
//重新设置Dst的实际大小(已经在解压缩过程当中进行重新分配)
Dst.Size := NewSize;
finally
DecompStream.Free;
end;
end; //测试代码
procedure Test;
var
SrcStream,PackedStream,UnpackedStream:TMemoryStream;
begin
SrcStream := TMemoryStream.Create;
try
SrcStream.LoadFromFile('c:\test.xml');
PackedStream := TMemoryStream.Create;
try
//压缩
PackStream(SrcStream, PackedStream); PackedStream.Seek(, soFromBeginning);
PackedStream.SaveToFile('c:\test_xml.pk');
UnpackedStream := TMemoryStream.Create;
try
//解压缩
UnpackStream(PackedStream, UnpackedStream); UnpackedStream.Seek(, soFromBeginning);
UnpackedStream.SaveToFile('c:\test_xml.xml');
finally
UnpackedStream.Free;
end;
finally
PackedStream.Free;
end;
finally
SrcStream.Free;
end;
end;

Delphi使用zlib来压缩文件

使用时,需要Zlib.pas和 Zlibconst.pas两个单元文件,这两个文件保存在 Delphi 5.0安装光盘上 InfoExtrasZlib目录下,此外,在 InfoExtrasZlibObj目录中还保存了 Zlib.pas单元引用的 Obj文件,把这个目录拷贝到delphi的lib下,即可。可以适当的改动比如增加目录压缩和分文件压缩,其实就是在文件流前面增加一部分描述结构就是,不多说。使用 时,还要use zlib单元。 两个函数如下:

procedure CompressIt(var CompressedStream: TMemoryStream; const CompressionLevel: TCompressionLevel);
// 参数是传递的流和压缩方式
var
  SourceStream: TCompressionStream;
  DestStream: TMemoryStream;
  Count: int64; //注意,此处修改了,原来是int
begin
  //获得流的原始尺寸
  Count := CompressedStream.Size;
  DestStream := TMemoryStream.Create;
  SourceStream := TCompressionStream.Create(CompressionLevel, DestStream);
  try
    //SourceStream中保存着原始的流
    CompressedStream.SaveToStream(SourceStream);
    //将原始流进行压缩, DestStream中保存着压缩后的流
    SourceStream.Free;
    CompressedStream.Clear;
    //写入原始图像的尺寸
    CompressedStream.WriteBuffer(Count, SizeOf(Count));
    //写入经过压缩的流
    CompressedStream.CopyFrom(DestStream, );
  finally
    DestStream.Free;
  end;
end; procedure UnCompressit(const CompressedStream: TMemoryStream; var UnCompressedStream: TMemoryStream);
//参数 压缩过的流,解压后的流
var
  SourceStream: TDecompressionStream;
  DestStream: TMemoryStream;
  Buffer: PChar;
  Count: int64;
begin
  //从被压缩的图像流中读出原始的尺寸
  CompressedStream.ReadBuffer(Count, SizeOf(Count));
  //根据尺寸大小为将要读入的原始流分配内存块
  GetMem(Buffer, Count);
  DestStream := TMemoryStream.Create;
  SourceStream := TDecompressionStream.Create(CompressedStream);
  try
    //将被压缩的流解压缩,然后存入 Buffer内存块中
    SourceStream.ReadBuffer(Buffer^, Count);
    //将原始流保存至 DestStream流中
    DestStream.WriteBuffer(Buffer^, Count);
    DestStream.Position := ; //复位流指针
    DestStream.Position := length(VER_INFO);
    //从DestStream流中载入图像流
    UnCompressedStream.LoadFromStream(DestStream);
  finally
    FreeMem(Buffer);
    DestStream.Free;
  end;
end;

使用的例子如下:

procedure TForm1.Button5Click(Sender: TObject);
//把指定文件压缩然后保存为另外一个压缩包,
//呵呵,我使用的时候是把后缀改成cab,可以唬一些人吧?
var
  SM: TMemoryStream;
begin
  if OpenDialog1.Execute then
  begin
    if SaveDialog1.Execute then
    begin
      SM := TMemoryStream.Create;
      try
        Sm.LoadFromFile(OpenDialog1.FileName);
        SM.Position := ;
        Compressit(sm, clDefault);
        sm.SaveToFile(SaveDialog1.FileName);
      finally
        SM.Free;
      end;
    end;
  end;
end; procedure TForm1.BitBtn2Click(Sender: TObject);
//把指定的压缩包解成原来的文件。
var
  SM, DM: TMemoryStream;
begin
  if OpenDialog1.Execute then
  begin
    if SaveDialog1.Execute then
    begin
      SM := TMemoryStream.Create;
      DM := TMemoryStream.Create;
      try
        Sm.LoadFromFile(OpenDialog1.FileName);
        SM.Position := ;
        UnCompressit(sm, dm);
        dm.Position := ;
        dm.SaveToFile(SaveDialog1.FileName);
      finally
        SM.Free;
        DM.Free;
      end;
    end;
  end;
end;

压缩与解压缩进度

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls; type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
ProgressBar1: TProgressBar;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure CsProgress(Sender: TObject); {压缩的 OnProgress 事件}
procedure DsProgress(Sender: TObject); {解压缩的 OnProgress 事件}
end; var
Form1: TForm1; implementation {$R *.dfm} uses Zlib; {压缩的 OnProgress 事件}
procedure TForm1.CsProgress(Sender: TObject);
begin
ProgressBar1.Position := Integer(TCompressionStream(Sender).Position div );
Application.ProcessMessages;
end; {解压缩的 OnProgress 事件}
procedure TForm1.DsProgress(Sender: TObject);
begin
ProgressBar1.Position := Integer(TDecompressionStream(Sender).Position div );
Application.ProcessMessages;
end; {压缩}
procedure TForm1.Button1Click(Sender: TObject);
var
cs: TCompressionStream;
fs,ms: TMemoryStream;
num: Integer;
begin
fs := TMemoryStream.Create;
fs.LoadFromFile('c:\temp\test.txt'); {我是用一个 15M 的文本文件测试的}
num := fs.Size; ms := TMemoryStream.Create;
ms.Write(num, SizeOf(num)); cs := TCompressionStream.Create(clMax, ms); {在原来代码基础是添加这两行}
ProgressBar1.Max := Integer(fs.Size div );
cs.OnProgress := CsProgress; fs.SaveToStream(cs);
cs.Free; ms.SaveToFile('c:\temp\test.zipx'); ms.Free;
fs.Free;
end; {解压缩}
procedure TForm1.Button2Click(Sender: TObject);
var
ds: TDecompressionStream;
fs,ms: TMemoryStream;
num: Integer;
begin
fs := TMemoryStream.Create;
fs.LoadFromFile('c:\temp\test.zipx');
fs.Position := ;
fs.ReadBuffer(num,SizeOf(num)); ms := TMemoryStream.Create;
ms.SetSize(num); ds := TDecompressionStream.Create(fs); {在原来代码基础是添加这两行}
ProgressBar1.Max := Integer(ms.Size div );
ds.OnProgress := DsProgress; ds.Read(ms.Memory^, num); ms.SaveToFile('c:\temp\test2.txt'); ds.Free;
ms.Free;
fs.Free;
end; end. 窗体文件:
object Form1: TForm1
Left =
Top =
Caption = 'Form1'
ClientHeight =
ClientWidth =
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch =
TextHeight =
object Button1: TButton
Left =
Top =
Width =
Height =
Caption = ##
TabOrder =
OnClick = Button1Click
end
object Button2: TButton
Left =
Top =
Width =
Height =
Caption = ###
TabOrder =
OnClick = Button2Click
end
object ProgressBar1: TProgressBar
Left =
Top =
Width =
Height =
TabOrder =
end
end

delphi 压缩的更多相关文章

  1. delphi 压缩ZLib

    system.ZLib http://docwiki.embarcadero.com/CodeExamples/Berlin/en/ZLibCompressDecompress_(Delphi) 还不 ...

  2. delphi压缩与解压_不需要特别的控件

    unit unzip; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  3. Delphi 解压缩 ZipForge

    ZipForge http://www.componentace.com/zip_component_zip_delphi_zipforge.htm downLoad http://www.compo ...

  4. Zlib压缩算法在Java与Delphi间交互实现(压缩XML交互)

    一个典型应用中,使用delphi作为客户端,J2EE服务端,两者之间用XML作为数据交换,为了提高效率,对XML数据进行压缩,为此需要找到一种压缩/解压算法能够两个平台之间交互处理,使用ZLIB算法就 ...

  5. delphi GDI 图片压缩代码 据说是位图缩放保持原图视觉效果最好的算法

    delphi 图片压缩代码 据说是位图缩放保持原图视觉效果最好的算法 若有更好的,请大神留言我也学习下,感谢! uses WinAPI.GDIPAPI, WinAPI.GDIPOBJ; var  Bi ...

  6. 使用zlib来压缩文件-用delphi描述

    今天用到压缩文件的问题,找了一些网上的资料,后来发现了delphi自身所带的zlib单元,根据例子稍微改变了一些,使它能够符合所有的格式. 使用时,需要Zlib.pas和 Zlibconst.pas两 ...

  7. 用DELPHI 开发压缩、解压、自解压、加密

    引 言:在日常中,我们一定使用过WINZIP.WINRAR这样的出名的压缩软件,就是我们开发软件过程中不免要遇到数据加密.数据压缩的问题!本文中就这一技术问题展开探讨,同时感谢各位网友的技巧,在我每次 ...

  8. Delphi XE2 新增 System.Zip 单元,压缩和解压缩文件

    Delphi XE2 新增 System.Zip 单元, 可用一句话压缩整个文件夹了 单元内主要就是 TZipFile 类, 最方便使用的是它的类方法: TZipFile.ExtractZipFile ...

  9. Delphi Base64编码/解码及ZLib压缩/解压

    最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结:   一.Base64编码/解码   一般用到的是Delphi自带的单元EncdDe ...

随机推荐

  1. js获取url参数值的几种方式

    一.原生js获取URL参数值: 比如当前URL为:http://localhost:8080/#/page2?id=100&name=guanxy <template> <d ...

  2. Jedis连接池的使用(转)

    http://www.cnblogs.com/linjiqin/archive/2013/06/14/3135248.html 所需jar:jedis-2.1.0.jar和commons-pool-1 ...

  3. rest framework 之前

    在开始rest framework之前,我们先来了解一下什么是restful rest 是一种软件架构风格,Representational state Transfer 它从资源的角度去看整个网络, ...

  4. Delphi 2010 XE 中使用 JSON 之 SuperObject68-6

    JSON之SuperObject(1):一直盼着Delphi能够直接支持"正则:Delphi2009刚来的时候,有了JSON,但:Delphi2010带了两个相关单元:DBXJS:我想不等了 ...

  5. /etc/X11/xorg.conf

    # This configuration file was broken by system-config-keyboard Section "ServerLayout" Iden ...

  6. delete 和 splice 删除数组中元素的区别

    delete 和 splice 删除数组中元素的区别 ` var arr1 = ["a","b","c","d"]; d ...

  7. 树莓派安装omv

    1.Win32DiskImager写入光盘镜像 2.进入omv页面 设置 ip 端口号 ,设置时间,设置ssh打开,设置会话超时时间 ××××设置 dns  很重要!! #这里用的是阿里云的DNS服务 ...

  8. 数据科学工作者(Data Scientist) 的日常工作内容包括什么

    数据科学工作者(Data Scientist) 的日常工作内容包括什么 众所周知,数据科学是这几年才火起来的概念,而应运而生的数据科学家(data scientist)明显缺乏清晰的录取标准和工作内容 ...

  9. CSP2019总结

    CSP2019总结 前言 赛前停课集训了两个星期,自认为已经准备充分了,结果... 不知道有没有写挂分,即使一分没挂,满打满算也只有400出头,还是太菜了. Day0 晚上复习了一会,打了会游戏就睡了 ...

  10. org.apache.hadoop.hbase.master.HMasterCommandLine: Master exiting java.lang.RuntimeException: HMaster Aborted

    前一篇的问题解决了,是 hbase 下面lib 包的jar问题,之前写MR的时候加错了包,替换掉了原来的包后出现另一问题:@ubuntu:/home/hadoop/hbase-0.94.6-cdh4. ...