分块压缩,
uses
zlib;
const C_SIZE =1000000;//大小1M作为一块压缩
function compressFile(SourFileName: string; DestFileName: string): boolean;
var
InStream: TFileStream;
OutStream: TfileStream;
ZStream: TCompressionStream;
E, I, ASize: integer;
buffer: Pchar;
flag: boolean; //压缩标识
begin
result := false;
i:=0;
e:=0;
Asize:=0;
if not fileexists(SourFileName) then begin result := false; exit; end;
try
Chdir(ExtractFilePath(ParamStr(0)));
//创建文件流
OutStream := Tfilestream.Create(destfilename, fmCreate or fmopenwrite);
//创建文件流
InStream := TFileStream.Create(SourFileName, fmOpenRead or fmShareExclusive);
//取得流大小
ASize := InStream.Size;
if Asize <> 0 then
begin
//在文件头写入源始文件大小,以便解压的时候读出源文件大小,否则就解压失败
OutStream.Write(ASize, SizeOf(ASize));
//clMax 压缩比最大 clNone, clFastest, clDefault, clMax
ZStream := TCompressionStream.Create(clDefault, OutStream);
//开始压缩标识
flag := true;
instream.Position := 0;
while flag do
begin
application.ProcessMessages;
{如文件小于1M就压缩全部}
if Asize<C_SIZE then
begin
e := asize;
flag := false;//标识结束
end
else if (asize - (i))< c_size then
begin
e := (asize - i);
flag := false;
end
else e := c_size;
inc(i, e);
//给buffer分配源文件大小的空间
getmem(buffer, e);
//将流的数据读入asize个字节到buffer指针中去
instream.Read(buffer^, e);
//将buffer中的数据写入压缩对象流outStream中,在写入压缩对象的同时压缩对象会自动压缩数据。
ZStream.Write(buffer^, e);
//清空缓存
freemem(buffer);
end;
outstream.Position := 0;
result := true;
end;
finally
instream.Free;
ZStream.Free;
end;
OutStream.Free;
end;
function UnCompressit(const CompressedStream: TfileStream; var DestStream: TfileStream): boolean; //解压
var
SourceStream: TDecompressionStream;
Buffer: PChar;
E, I, Count: integer;
Flag: boolean;
begin
result := false;
count := 0;
i := 0;
e:=0;
//从文件头读出4个字节的数据,这一段是压缩时写进去的源文件大小
CompressedStream.ReadBuffer(count, sizeof(count));
try
//创建解压对象流
SourceStream := TDecompressionStream.Create(CompressedStream);
flag := true;
while flag do
begin
if C_SIZE > count then
begin
e := count;
flag := false;
end
else if c_size > (count - (i)) then
begin
e := (count - i);
flag := false;
end
else e := c_size;
inc(i, e);
application.ProcessMessages; //交系统处理,以免出现画面停止现象
GetMem(Buffer, e); //分配源文件大小的内存
SourceStream.Read(Buffer^, e); //把解压流中的数据读count个到内存中,解压对象在读出数据的同时会自动解压文件
DestStream.Write(Buffer^, e); //把内存中的数据写count个到destStream中去
FreeMem(Buffer);
end;
DestStream.Position := 0; //读取指针回位
result := true;
finally
SourceStream.Free; //释放解压对象
end;
end;