求壓縮文件的代碼? (100分)

  • 主题发起人 主题发起人 周子
  • 开始时间 开始时间

周子

Unregistered / Unconfirmed
GUEST, unregistred user!
用delphi編寫一段壓縮文件的功能,誰有代碼,貼出來認我看看,感激不盡
 
 Borland公司推出的 RAD开发工具 Delphi 5.0作为 Windows平台上的主流开发工具,其可视化的开发环境和面向对象编程的强大功能已经吸引了无数的开发人员。但是,一些程序员在实际的开发过程中却时常为对大量的数据进行压缩而伤透脑筋,不得不去查找一些高效的压缩算法或在网上查找第三方的控件来实现压缩。难道 Delphi本身没有提供这个功能吗?其实 Delphi的程序设计师早就考虑到了这一点,他们提供了 Zlib.pas和 Zlibconst.pas两个单元文件来解决数据压缩问题,实现了很高的数据压缩比率。这两个文件保存在 Delphi 5.0安装光盘上 /Info/Extras/Zlib目录下,此外,在 Info/Extras/Zlib/Obj目录中还保存了 Zlib.pas单元引用的 Obj文件。下面本文以压缩一个屏幕拷贝为例介绍如何使用这项功能。
  解决思路
  首先利用屏幕拷贝捕捉到当前整个屏幕的图像,然后在内存中保存为 BMP文件格式。压缩时,使用 TCompressionStream对象对原始图像进行压缩并且保存为自定义的文件格式;解压缩时,使用 TDecompressionStream对象对被压缩的图像进行解压缩,还原为 BMP格式的图像文件。
  具体实现
  新建一个项目文件,在主单元的接口部分引用 Zlib.pas,在主表单上放置两个按钮 Button1、 Button2,在它们的 OnClick事件中写上相应的过程调用代码。
  部分程序源代码如下:
  unit Unit1;
  interface
  uses
   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls, Zlib;
   type
    TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
   private
    { Private declarations }
   public
    { Public declarations }
   end;

   var
    Form1: TForm1;
    implementation
     {$ R* .DFM}
   1.捕捉全屏幕图像
    procedure GetScreen(var Bmp: TBitmap);
    var
     Dc: HDC;
     MyCanvas: TCanvas;
     MyRect: TRect;
    begin

     Dc := GetWindowDC(0);
     MyCanvas := TCanvas.Create;
    try
     MyCanvas.Handle := Dc;
     MyRect:=Rect(0, 0,Screen.Width, Screen.Height);
     file://图像为 24位真彩色,也可根据实际需要调整
     Bmp.PixelFormat := pf24bit;
     Bmp.Width := MyRect.Right;
     Bmp.Height := MyRect.Bottom;
     file://捕捉整个屏幕图像
     Bmp.Canvas.CopyRect(MyRect, MyCanvas, MyRect);
     finally
     MyCanvas.Handle := 0;
     MyCanvas.Free;
     ReleaseDC(0, Dc);
    end;

   end;

Delphi数据压缩处理 2
  2.压缩图像
   procedure CompressBitmap(var CompressedStream: TMemoryStream;const CompressionLevel: TCompressionLevel);
    var
     SourceStream: TCompressionStream;
     DestStream: TMemoryStream;
     Count: Integer;
    begin

     file://获得图像流的原始尺寸
     Count := CompressedStream.Size;
     DestStream := TMemoryStream.Create;
     SourceStream:=TCompressionStream.Create
     (CompressionLevel, DestStream);
     Try
      file://SourceStream中保存着原始的图像流
      CompressedStream.SaveToStream(SourceStream);
      file://将原始图像流进行压缩, DestStream中保存着压缩后的图像流
      SourceStream.Free;
      CompressedStream.Clear;
      file://写入原始图像的尺寸
      CompressedStream.WriteBuffer(Count, SizeOf
      (Count));
      file://写入经过压缩的图像流
      CompressedStream.CopyFrom(DestStream, 0);
      finally
      DestStream.Free;
     end;

    end;

Delphi数据压缩处理 3
   3.还原被压缩图像
    procedure UnCompressBitmap(const CompressedStream: TFileStream;
var Bmp: TBitmap);
     var
      SourceStream: TDecompressionStream;
      DestStream: TMemoryStream;
      Buffer: PChar;
      Count: Integer;
     begin

      file://从被压缩的图像流中读出原始图像的尺寸
      CompressedStream.ReadBuffer(Count, SizeOf(Count));
      file://根据图像尺寸大小为将要读入的原始图像流分配内存块
      GetMem(Buffer, Count);
      DestStream := TMemoryStream.Create;
      SourceStream := TDecompressionStream.Create(CompressedStream);
     Try
      file://将被压缩的图像流解压缩,然后存入 Buffer内存块中
      SourceStream.ReadBuffer(Buffer^, Count);
      file://将原始图像流保存至 DestStream流中
      DestStream.WriteBuffer(Buffer^, Count);
      DestStream.Position := 0;//复位流指针
      //从 DestStream流中载入原始图像流
      Bmp.LoadFromStream(DestStream);
      finally
      FreeMem(Buffer);
      DestStream.Free;
     end;

    end;

   4.压缩按钮 OnClick事件
    procedure TForm1.Button1Click(Sender: TObject);
     var
      Bmp: TBitmap;
      CompressedStream: TMemoryStream;
     begin

      Bmp := TBitmap.Create;
      CompressedStream := TMemoryStream.Create;
     Try
       file://捕获当前整个屏幕 ,将图像保存至 Bmp对象中 GetScreen(Bmp);
      file://将 Bmp对象中的图像保存至内存流中
      Bmp.SaveToStream(CompressedStream);
      file://按缺省的压缩比例对原始图像流进行压缩
      CompressBitmap(CompressedStream, clDefault);
      file://将压缩之后的图像流保存为自定义格式的文件
      CompressedStream.SaveToFile(‘ C:/cj.dat’ );
      finally
      Bmp.Free;
      CompressedStream.Free;
     end;

    end;

   5.解压缩按钮 OnClick事件
     procedure TForm1.Button2Click(Sender: TObject);
      var
       CompressedStream: TFileStream;
       Bmp: TBitmap;
      begin

       Bmp := TBitmap.Create;
       file://以文件流的只读方式打开自定义的压缩格式文件
       CompressedStream := TFileStream.Create(‘ C:/cj.dat’ , fmOpenRead);
      Try
       file://将被压缩的图像流进行解压缩
       UnCompressBitmap(CompressedStream, Bmp);
       file://将原始图像流还原为指定的 BMP文件
       Bmp.SaveToFile(‘ C:/cj.bmp’ );
       finally
       Bmp.Free;
       CompressedStream.Free;
      end;

      end;

  此外 TCompressionStream对象还提供了 CompressionRate属性,该属性用于描述对原始数据进行压缩后的压缩比率,而 OnProgress事件在压缩与解压缩过程中都会被触发,开发人员可以在该事件中编写用于显示进度的代码。
  以上代码在 Delphi 5.0中调试运行通过。
 
用控件,胜天进销存用过一个压缩控件vclzip2.23
 
to app2001
我在delphi6運行會出錯,運行到 file:
會出以下的錯誤
[Error] Zlib_u.pas(38): '(' expected but ':' found
 
你是直接拷代码过去的吧,里面或许有一些看不见的异常字符,你最好自己在出错的地方全删掉,再自己打一次
 
to app2001
奇怪,我按你方法去做,還是同樣的錯誤,怎麼辦
 
File:的作用是什麼,它的用法我不太明白
 
to app2001
GetScreen這個過程我看下面沒有調用,可否不用
 
還是沒用,是否在delphi6下編繹不了
 
和wiwei兄弟一樣,我一個個輸入進去,還是編繹不了
 
uses
ZLib;

{ Compress a stream }
procedure CompressStream(inpStream, outStream: TStream);
var
InpBuf, OutBuf: Pointer;
InpBytes, OutBytes: Integer;
begin

InpBuf := nil;
OutBuf := nil;
try
GetMem(InpBuf, inpStream.Size);
inpStream.Position := 0;
InpBytes := inpStream.Read(InpBuf^, inpStream.Size);
CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
outStream.Write(OutBuf^, OutBytes);
finally
if InpBuf <> nil then
FreeMem(InpBuf);
if OutBuf <> nil then
FreeMem(OutBuf);
end;

end;


{ Decompress a stream }
procedure DecompressStream(inpStream, outStream: TStream);
var
InpBuf, OutBuf: Pointer;
OutBytes, sz: Integer;
begin

InpBuf := nil;
OutBuf := nil;
sz := inpStream.Size - inpStream.Position;
if sz > 0 then

try
GetMem(InpBuf, sz);
inpStream.Read(InpBuf^, sz);
DecompressBuf(InpBuf, sz, 0, OutBuf, OutBytes);
outStream.Write(OutBuf^, OutBytes);
finally
if InpBuf <> nil then
FreeMem(InpBuf);
if OutBuf <> nil then
FreeMem(OutBuf);
end;

outStream.Position := 0;
end;


{
Example:
Compress the contents of RichEdit1 and
calculate the compression rate.
then
save the stream to a file (ms2.dat)
Beispiel:
Komprimiert den Inhalt von RichEdit1 und
berechnet die Kompressionsrate.
Dann wird der Stream in eine Datei (ms2.dat) gespeichert.
}
procedure TForm1.Button1Click(Sender: TObject);
var
ms1, ms2: TMemoryStream;
begin

ms1 := TMemoryStream.Create;
try
ms2 := TMemoryStream.Create;
try
RichEdit1.Lines.SaveToStream(ms1);
CompressStream(ms1, ms2);
ShowMessage(Format('Stream Compression Rate: %d %%',
[round(100 / ms1.Size * ms2.Size)]));
ms2.SaveToFile('C:/ms2.dat');
finally
ms1.Free;
end;

finally
ms2.Free;
end;

end;

{
Loads the stream from a file (ms2.dat)
and decompresses it.
then
loads the Stream to RichEdit1.
L&amp;auml;dt den komprimierten Stream von einer Datei (ms2.dat)
und dekomprimiert ihn.
Dann wird der Stream wieder in RichEdit1 geladen.
}
procedure TForm1.Button2Click(Sender: TObject);
var
ms1, ms2: TMemoryStream;
begin

ms1 := TMemoryStream.Create;
try
ms2 := TMemoryStream.Create;
try
ms1.LoadFromFile('C:/ms2.dat');
DecompressStream(ms1, ms2);
RichEdit1.Lines.LoadFromStream(ms2);
finally
ms1.Free;
end;

finally
ms2.Free;
end;

end;

**********************************
procedure Compress(var CompressedStream: TMemoryStream);
var
SourceStream: TCompressionStream;
DestStream: TMemoryStream;
Count: Integer;
begin
Count := CompressedStream.Size;
DestStream := TMemoryStream.Create;
SourceStream:=TCompressionStream.Create(clMax, DestStream);
Try
CompressedStream.SaveToStream(SourceStream);
SourceStream.Free;
CompressedStream.Clear;
CompressedStream.WriteBuffer(Count, SizeOf(Count));
CompressedStream.CopyFrom(DestStream, 0);
finally
DestStream.Free;
end;
end;

procedure UnCompress(const CompressedStream: TMemoryStream);
var
SourceStream: TDecompressionStream;
DestStream: TMemoryStream;
Buffer: PChar;
Count: integer;
begin
CompressedStream.Seek(0,soFrombegin
ning);
CompressedStream.ReadBuffer(Count, SizeOf(Count));
GetMem(Buffer, Count);
DestStream := TMemoryStream.Create;
SourceStream := TDecompressionStream.Create(CompressedStream);
Try
SourceStream.ReadBuffer(Buffer^, Count);
DestStream.WriteBuffer(Buffer^, Count);
DestStream.Position := 0;//复位流指针
CompressedStream.LoadFromStream(DestStream);
finally
FreeMem(Buffer);
DestStream.Free;
end;
end;
 
這個能壓縮,但不能解壓縮,我有一個200多M的壓縮成1KB,但不能解壓縮.
 
200+M的东东压成1K ????
看起来是项尖端的技术,但实际是程序错了.
 
不是程序錯了,我是用錯了,要加上點東東就可以了謝了
 
用richedit好像不能讀入 dat的文件,把dat的文件壓縮用什麼辦法
 
unit Unit1;
interface
uses
Windows,
Messages,
SysUtils,
Variants,
Classes,
Graphics,
Controls,
Forms,
Dialogs,
StdCtrls,
ComCtrls,
Zlib;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
RichEdit1: TRichEdit;
OpenDialog1: TOpenDialog;
SaveDialog1: TSaveDialog;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
S: string;
end;

var
Form1 : TForm1;
implementation
uses unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
InStream : TFileStream;
OutStream : TMemoryStream;
ZStream : TCompressionStream;
ASize : Integer;
begin
if OpenDialog1.Execute then
begin
RichEdit1.Lines.Add('打开: ' + OpenDialog1.FileName);
S := ExtractFilePath(OpenDialog1.FileName) +
ExtractFileName(OpenDialog1.FileName) + '.app';
Chdir(ExtractFilePath(ParamStr(0)));
InStream := TFileStream.Create(ExpandFileName(OpenDialog1.FileName),
fmOpenRead or fmShareDenyNone);
ASize := InStream.Size;
try
OutStream := TMemoryStream.Create;
try
OutStream.Write(ASize, SizeOf(ASize));
ZStream := TCompressionStream.Create(clFastest, OutStream);
try
ZStream.CopyFrom(InStream, 0);
finally
ZStream.Free;
end;
OutStream.SaveToFile(S);
finally
OutStream.Free;
end;
finally
InStream.Free;
end;
RichEdit1.Lines.Add('压缩: ' + S + ' 成功!');
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
D : string;
InStream, OutStream: TMemoryStream;
ZStream : TDecompressionStream;
ASize : Integer;
begin
if SaveDialog1.Execute then
begin
RichEdit1.Lines.Add('解压: ' + S);
InStream := TMemoryStream.Create;
try
InStream.LoadFromFile(S);
OutStream := TMemoryStream.Create;
try
InStream.Position := 0;
InStream.Read(ASize, SizeOf(ASize));
ZStream := TDecompressionStream.Create(InStream);
try
OutStream.CopyFrom(ZStream, ASize);
finally
ZStream.Free;
end;
D := SaveDialog1.FileName;
OutStream.SaveToFile(D);
finally
OutStream.Free;
end;
finally
InStream.Free;
end;
RichEdit1.Lines.Add('解压: ' + D +' 成功!');
end;
end;

end.

这样因该可以了。
 
如果你想自己做的话,不妨参考一下VCLZIP的原理,网上不难找到源码。
 
to app2001
謝謝你了,其實我修改好了:
procedure TForm1.Button1Click(Sender: TObject);
var
ms1, ms2: TMemoryStream;
// l1:file;
begin
ms1 := TMemoryStream.Create;
try
ms2 := TMemoryStream.Create;
try
with opendialog1 do
if execute then
begin
ms1.LoadFromFile(filename);
end;
// RichEdit1.Lines.SaveToStream(ms1);
CompressStream(ms1, ms2);
ShowMessage(Format('Stream Compression Rate: %d %%',
[round(100 / ms1.Size * ms2.Size)]));
ms2.SaveToFile('C:/ms2.rar');
finally
ms1.Free;
end;
finally
ms2.Free;
end;

end;
 
接受答案了.
 
后退
顶部