用DELPHI實現文件加密壓縮

  用DELPHI實現文件加密壓縮
  作者: e夢緣 (wnhoo)
  Mail:wnhoo@163.com
  風花雪月 e夢情緣
  
用DELPHI實現文件加密壓縮
點擊下載此詳細說明文件
  概述:
  在這篇文件中,講述對單個文件的數據加密、數據壓縮、自解壓的實現。同樣,也可以實現對多個文件或文件夾的壓縮,只要稍加修改便可實現。
  關鍵字:加密壓縮、Zlib、流、資源文件
  引言:
  在日常中,我們一定使用過WINZip、WINRAR這樣的出名的壓縮軟件,就是我們開發軟件過程中不免要遇到數據加密、數據壓縮的問題!本文中就這一技術問題展開探討,同時感謝各位網友的技巧,在我每次面對問題要解決的時候,是你們辛苦地摸索出來的技巧總是讓我豁然開朗,問題迎刃而解。本篇文章主要是運用DELPH的強大的流處理方面的技巧來實現的數據加密壓縮,並用于實際的軟件程序開發中,將我個人的心得、開發經驗寫出來與大家分享。
  1、 系統功能
  1)、數據壓縮
  使用DELPHI提供的兩個流類(TComPRessionStream和TDecompressionStream)來完成數據的壓縮和解壓縮。
  2)、數據加密壓縮
  通過Delphi編程中「流」的應用實現數據加密,主要采用Tstream的兩個派生類Tfilestream、Tmemorystream 來完成的;其中數據壓縮部分采用1)的實現方法
  3)、雙擊壓縮文件自動關聯解壓
  通過更改注冊表的實現擴展名與程序文件的關聯,主要采用Tregistry;並且,API函數SHChangeNotify實現注冊效果的立即呈現。
  4)、可生成自解壓文件
  自解壓的文件實現數據壓縮1)與數據加密壓縮2)的自動解壓;並且,通過資源文件的使用實現可執行的自解壓文件與數據文件的合並,來完成數據的自解壓實現。
  2、 系統實現
  2.1、工作原理
  
用DELPHI實現文件加密壓縮

  2.2、關鍵技術的講述
  (一)ZLIB
  1)、基類 TCustomZlibStream:是類TCompressionStream和TDecompressionStream 類的基類,它主要有一個屬性: OnProgress,在類進行壓縮或解壓縮的過程中會發生這個的事件 。
  格式:Procedure OnProgress (Sender: TObject); dynamic;
  2)、壓縮類TCompressionStream:除了繼承了基類的OnProgress 屬性外,又增加了一個屬性:CompressionRate,它的定義如下:
  Property CompressionRate: Single read GetCompressionRate;
  通過這個屬性,可以得到壓縮比。
  它的幾個重要的方法定義如下:
  Constructor TCompressionStream.Create (CompressionLevel: TCompressionLevel; Dest: TStream);
  其中:TcompressionLevel(壓縮類型),它由如下幾個定義:
  1)、 clNone :不進行數據壓縮;
  2)、 clFastest:進行快速壓縮,犧牲壓縮效率;
  3)、 clDefault:進行正常壓縮;
  4)、 clMax: 進行最大化壓縮,犧牲速度;
  Dest:目的流,用于存放壓縮過的數據。
  Function TCompressionStream.Write (const Buffer; Count: Longint): Longint;
  其中:Buffer:需要壓縮的數據;
  Count: 需要壓縮的數據的字節數;
  函數返回寫入流的字節數。
  注意:壓縮類TCompressionStream的數據只能是寫入的,如果試圖從其內部讀取數據,將發生一個"Error "異常。需要壓縮的數據通過方法 Write寫入流中,在寫入的過程中就被壓縮,並保存在由構造函數提供的內存流(TmemoryStream)中,同時觸發 OnProcess 事件。
  3)、 解壓縮類 TDecompressionStream :和壓縮類TcompressionStream相反,它的數據是只能讀出的,如果試圖往其內部寫數據,將發生一個"Error "異常。
  它的幾個重要方法定義如下:
  構造函數:Constructor Create(Source: TStream);
  其中:Source 是保存著壓縮數據的流;
  Function Read(var Buffer; Count: Longint): Longint;
  數據讀出函數,Buffer: 存數據緩沖區;Count: 緩沖區的大小;
  函數返回讀出的字節數。數據在讀出的過程中,數據被解壓縮,並觸發 OnProcess 事件。
  (二)流
  在Delphi中,所有流對象的基類爲TStream類,其中定義了所有流的共同屬性和方法。
  TStream類中定義的屬性如下:
  1)、Size:此屬性以字節返回流中數據大小。
  2)、Position:此屬性控制流中存取指針的位置。
  Tstream中定義的虛方法有四個:
  1)、Read:此方法實現將數據從流中讀出,返回值爲實際讀出的字節數,它可以小于或等于指定的值。
  2)、Write:此方法實現將數據寫入流中,返回值爲實際寫入流中的字節數。
  3)、Seek:此方法實現流中讀取指針的移動,返回值爲移動後指針的位置。
  函數原形爲:Function Seek(Offset:Longint;Origint:Word):Longint;virtual;abstract;
  參數Offset爲偏移字節數,參數Origint指出Offset的實際意義,其可能的取值如下:
  soFromBeginning:Offset爲指針距離數據開始的位置。此時Offset必須大于或者等于零。
  soFromCurrent:Offset爲移動後指針與當前指針的相對位置。
  soFromEnd:Offset爲移動後指針距離數據結束的位置。此時Offset必須小于或者等于零。
  4)、Setsize:此方法實現改變數據的大小。
  另外,TStream類中還定義了幾個靜態方法:
  1)、ReadBuffer:此方法的作用是從流中當前位置讀取數據,跟上面的Read相同。
  注意:當讀取的數據字節數與需要讀取的字節數不相同時,將産生EReadError異常。
  2)、WriteBuffer:此方法的作用是在當前位置向流寫入數據,跟上面的Write相同。
  注意:當寫入的數據字節數與需要寫入的字節數不相同時,將産生EWriteError異常。
  3)、CopyFrom:此方法的作用是從其它流中拷貝數據流。
  函數原形爲:Function CopyFrom(Source:TStream;Count:Longint):Longint;
  參數Source爲提供數據的流,Count爲拷貝的數據字節數。當Count大于0時,CopyFrom從Source參數的當前位置拷貝Count個字節的數據;當Count等于0時,CopyFrom設置Source參數的Position屬性爲0,然後拷貝Source的所有數據;
  Tstream常見派生類:
  TFileStream (文件流的存取)
  TStringStream (處理內存中的字符串類型數據)
  TmemoryStream (對于工作的內存區域數據處理)
  TBlobStream (BLOB類型字段的數據處理)
  TwinSocketStream (socket的讀寫處理)
  ToleStream (COM接口的數據處理)
  TresourceStream (資源文件流的處理)
  其中最常用的是TFileStream類。使用TFileStream類來存取文件,首先要建立一個實例。聲明如下:
  constructor Create(const Filename:string;Mode:Word);
  Filename爲文件名(包括路徑)
  Mode爲打開文件的方式,它包括文件的打開模式和共享模式,其可能的取值和意義如下:
  打開模式:
  fmCreate :用指定的文件名建立文件,如果文件已經存在則打開它。
  fmOpenRead :以只讀方式打開指定文件
  fmOpenWrite :以只寫方式打開指定文件
  fmOpenReadWrite:以寫寫方式打開指定文件
  共享模式:
  fmShareCompat :共享模式與FCBs兼容
  fmShareExclusive:不允許別的程序以任何方式打開該文件
  fmShareDenyWrite:不允許別的程序以寫方式打開該文件
  fmShareDenyRead :不允許別的程序以讀方式打開該文件
  fmShareDenyNone :別的程序可以以任何方式打開該文件
  (三)資源文件
  1)、創建資源文件
  首先創建一個.Rc的純文本文件。
  格式: 資源標識符 關鍵字 資源文件名
  資源標識符:程序中調用資源時的特殊標號;
  關鍵字:標識資源文件類型;
  Wave: 資源文件是聲音文件;
  RCDATA: JPEG文件;
  AVI: AVI動畫;
  ICON: 圖標文件;
  BITMAP: 位圖文件;
  CURSOR: 光標文件;
  EXEFILE : EXE文件
  資源文件名:資源文件的在磁盤上存儲的文件全名
  例如:
  myzjy exefile zjy.exe
  2)、編譯資源文件
  在DELPHI的安裝目錄的\Bin下,使用BRCC32.exe編譯資源文件.RC。當然,也可以將BRCC32單獨拷貝到程序文檔目錄使用。
  例如:
  Brcc32 wnhoo_reg.Rc
  3)、資源文件引用
  …
  implementation
  {$R *.dfm}
  {$R wnhoo_reg.Res}
  …
  4)、調用資源文件
  (1)存取資源文件中的位圖(Bitmap)
  Image.Picture.Bitmap.Handle :=LoadBitmap(hInstance,'資源標識符');
  注:如果位圖沒有裝載成功,程序仍舊執行,但是Image將不再顯示圖片。你可以根據LoadBitmap函數的返回值判斷是否裝載成功,如果裝載成功返回值是非0,如果裝載失敗返回值是0。
  另外一個存取顯示位圖的方法如下
  Image.Picture.Bitmap.LoadFromResourceName(hInstance,'資源標識符');
  (2)存取資源文件中的光標
  Screen.Cursors[]是一個光標數組,使用光標文件我們可以將定制的光標加入到這個屬性中。因爲默認的光標在數組中索引值是0,所以除非想取代默認光標,最好將定制的光標索引值設爲1。
  Screen.Cursors[1] :=LoadCursor(hInstance,'資源標識符');
  Image.Cursor :=1;
  (3)存取資源文件中的圖標
  將圖標放在資源文件中,可以實現動態改變應用程序圖標。
  application.Icon.Handle := LoadIcon(hInstance,'資源標識符');
  (4)存取資源文件中的AVI
  Animate.ResName :='MyAvi' ; //資源標識符號
  Animate.Active :=True ;
  (5)存取資源文件中的JPEG
  把jpeg單元加入到uses單元中。
  var
  Fjpg : TJpegImage ;
  FStream :TResourceStream ;
  begin
  Fjpg :=TJpegImage.Create ;
  //TresourceStream使用
  FStream := TResourceStream.Create (Hinstance,'資源標識符',資源類型) ;
  FJpg.LoadFromStream (FStream) ;
  Image.Picture.Bitmap.Assign (FJpg);
  (6)存取資源文件中的Wave
  把MMSystem加入uses單元中
  PlaySound(pchar('mywav'),Hinstance,Snd_ASync or Snd_Memory or snd_Resource) ;
  (四)INI文件操作
  (1) INI文件的結構:
  ;這是關于INI文件的注釋部分
  [節點]
  關鍵字=值
  ...
  INI文件允許有多個節點,每個節點又允許有多個關鍵字, 「=」後面是該關鍵字的值(類型有三種:字符串、整型數值和布爾值。其中字符串存貯在INI文件中時沒有引號,布爾真值用1表示,布爾假值用0表示)。注釋以分號「;」開頭。
  (2) INI文件的操作
  1、 在Interface的Uses節增加IniFiles;
  2、 在Var變量定義部分增加一行:inifile:Tinifile;然後,就可以對變量myinifile進行創建、打開、讀取、寫入等操作了。
  3、 打開INI文件:inifile:=Tinifile.create('tmp.ini');
  4、 讀取關鍵字的值:
  a:=inifile.Readstring('節點','關鍵字',缺省值);// string類型
  b:=inifile.Readinteger('節點','關鍵字',缺省值);// integer類型
  c:=inifile.Readbool('節點','關鍵字',缺省值);// boolean類型
  其中[缺省值]爲該INI文件不存在該關鍵字時返回的缺省值。
  5、 寫入INI文件:
  inifile.writestring('節點','關鍵字',變量或字符串值);
  inifile.writeinteger('節點','關鍵字',變量或整型值);
  inifile.writebool('節點','關鍵字',變量或True或False);
  當這個INI文件的節點不存在時,上面的語句還會自動創建該INI文件。
  6、 刪除關鍵字:
  inifile.DeleteKey('節點','關鍵字');//關鍵字刪除
  inifile.EraseSection('節點');// 節點刪除
  7、 節點操作:
  inifile.readsection('節點',TStrings變量);//可將指定小節中的所有關鍵字名讀取至一個字符串列表變量中;
  inifile.readsections(TStrings變量);//可將INI文件中所有小節名讀取至一個字符串列表變量中去。
  inifile.readsectionvalues('節點',TStrings變量);//可將INI文件中指定小節的所有行(包括關鍵字、=、值)讀取至一個字符串列表變量中去。
  8、 釋放:inifile.distory;或inifile.free;
  (五)文件關聯
  uses
  registry, shlobj;
  //實現關聯注冊
  procedure Tmyzip.regzzz;
  var
  reg: TRegistry;
  begin
  reg := TRegistry.Create;
  reg.RootKey := HKEY_CLASSES_ROOT;
  reg.OpenKey('.zzz', true);
  reg.WriteString('', 'myzip');
  reg.CloseKey;
  reg.OpenKey('myzip\shell\open\command', true);
  //用于打開.zzz文件的可執行程序
  reg.WriteString('', '"' + application.ExeName + '" "%1"');
  reg.CloseKey;
  reg.OpenKey('myzip\DefaultIcon',true);
  //取當前可執行程序的圖標爲.zzz文件的圖標
  reg.WriteString('',''+application.ExeName+',0');
  reg.Free;
  //立即刷新
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
  end;
  2.3、加密壓縮的實現
  1、 生成INI臨時加密文件
  用于加密的INI的臨時文件格式:
  [FILE1]//節點,在軟件中使用FILE1..N可以實現多文件加密
  FILENAME=壓縮文件名
  PASSWORD=解壓密碼
  FILESIZE=文件大小
  FILEDATE=創建日期
  ISJM=解壓是否需要密碼
  如果是實現多文件、文件夾的信息存儲,可以將密碼關鍵字存在一個總的節點下。本文中僅是實現對單個文件的加密,所以只要上述格式就可以了。
  2、 將數據文件與用于加密的INI文件的合並,這可以采用文件流的形式實現。
  加密後文件結構圖:
  圖(1)
  圖(2)
  上面兩種形式,可以根據實際采用。本文采用圖(1)的結構。
  3、 對于加密後的數據,采用ZLIB技術實現壓縮存儲,生成新壓縮形式的文件。
  2.4、文件關聯的實現 見2.2 (五)
  2.5、自解壓的實現
  1. 建立一個專門用來自解壓的可執行程序文件
  2. 將1中建立的文件,生成資源文件
  3. 將資源文件放到本文中這個壓縮工具的程序中一起編譯。
  4. 通過將資源文件與壓縮文件的合並,生成自解壓文件。
  自解壓文件結構圖:
  5.自解壓實現:通過將自身文件中的加密壓縮數據的分解,然後對分解的加密壓縮數據再一次解壓並分解出真正的數據文件。
  2.6 系統程序設計
  這是關于這個軟件實現的核心部分全部代碼,在這裏詳細講述這個軟件所有的技術細節。
  // wnhoo_zzz.pas
  unit wnhoo_zzz;
  interface
  uses
  Windows,Forms,SysUtils,Classes,zlib,Registry,INIFILES, Dialogs, shlobj;
  type
  pass=string[20];
  type
  Tmyzip = class
  private
  { private declarations here}
  protected
  { protected declarations here }
  public
  procedure regzzz;
  procedure ys_file(infileName, outfileName: string;password:pass;isjm:boolean;ysbz:integer);
  function jy_file(infileName: string;password:pass=''):boolean;
  procedure zjywj(var filename:string);
  constructor Create;
  destructor Destroy; override;
  { public declarations here }
  published
  { published declarations here }
  end;
  implementation
  constructor Tmyzip.Create;
  begin
  inherited Create; // 初始化繼承下來的部分
  end;
  //#####################################################
  //原文件加密
  procedure jm_File(vfile:string;var Target:TMemoryStream;password:pass;isjm:boolean);
  {
  vfile:加密文件
  target:加密後輸出目標流 》》》
  password:密碼
  isjm:是否加密
  -------------------------------------------------------------
  加密後文件SIZE=原文件SIZE+[INI加密壓縮信息文件]的SIZE+存儲[INI加密壓縮信息文件]的大小數據類型的SIZE
  ---------------------------------------------------------------
  }
  var
  tmpstream,inistream:TFileStream;
  FileSize:integer;
  inifile:TINIFILE;
  filename:string;
  begin
  //打開需要 [加密壓縮文件]
  tmpstream:=TFileStream.Create(vFile,fmOpenread or fmShareExclusive);
  try
  //向 [臨時加密壓縮文件流] 尾部寫入 [原文件流]
  Target.Seek(0,soFromEnd);
  Target.CopyFrom(tmpstream,0);
  //取得文件路徑 ,生成 [INI加密壓縮信息文件]
  filename:=ExtractFilePath(paramstr(0))+'tmp.in_';
  inifile:=TInifile.Create(filename);
  inifile.WriteString('file1','filename',ExtractFileName(vFile));
  inifile.WriteString('file1','password',password);
  inifile.WriteInteger('file1','filesize',Target.Size);
  inifile.WriteDateTime('file1','fileDate',now());
  inifile.WriteBool('file1','isjm',isjm);
  inifile.Free ;
  //讀入 [INI加密壓縮信息文件流]
  inistream:=TFileStream.Create(filename,fmOpenread or fmShareExclusive);
  try
  //繼續在 [臨時加密壓縮文件流] 尾部加入 [INI加密壓縮信息文件]
  inistream.Position :=0;
  Target.Seek(0,sofromend);
  Target.CopyFrom(inistream,0);
  //計算當前 [INI加密壓縮信息文件] 的大小
  FileSize:=inistream.Size ;
  //繼續在 [臨時加密文件尾部] 加入 [INI加密壓縮信息文件] 的SIZE信息
  Target.WriteBuffer(FileSize,sizeof(FileSize));
  finally
  inistream.Free ;
  deletefile(filename);
  end;
  finally
  tmpstream.Free;
  end;
  end;
  //**************************************************************
  //流壓縮
  procedure ys_stream(instream, outStream: TStream;ysbz:integer);
  {
  instream: 待壓縮的已加密文件流
  outStream 壓縮後輸出文件流
  ysbz:壓縮標准
  }
  var
  ys: TCompressionStream;
  begin
  //流指針指向頭部
  inStream.Position := 0;
  //壓縮標准的選擇
  case ysbz of
  1: ys := TCompressionStream.Create(clnone,OutStream);//不壓縮
  2: ys := TCompressionStream.Create(clFastest,OutStream);//快速壓縮
  3: ys := TCompressionStream.Create(cldefault,OutStream);//標准壓縮
  4: ys := TCompressionStream.Create(clmax,OutStream); //最大壓縮
  else
  ys := TCompressionStream.Create(clFastest,OutStream);
  end;
  try
   //壓縮流
   ys.CopyFrom(inStream, 0);
  finally
   ys.Free;
  end;
  end;
  //*****************************************************************
  //流解壓
  procedure jy_Stream(instream, outStream: TStream);
  {
  instream :原壓縮流文件
  outStream:解壓後流文件
  }
  var
  jyl: TDeCompressionStream;
  buf: array[1..512] of byte;
  sjread: integer;
  begin
  inStream.Position := 0;
  jyl := TDeCompressionStream.Create(inStream);
  try
   repeat
   //讀入實際大小
   sjRead := jyl.Read(buf, sizeof(buf));
   if sjread > 0 then
   OutStream.Write(buf, sjRead);
   until (sjRead = 0);
  finally
   jyl.Free;
  end;
  end;
  //**************************************************************
  //實現關聯注冊
  procedure Tmyzip.regzzz;
  var
  reg: TRegistry;
  begin
  reg := TRegistry.Create;
  reg.RootKey := HKEY_CLASSES_ROOT;
  reg.OpenKey('.zzz', true);
  reg.WriteString('', 'myzip');
  reg.CloseKey;
  reg.OpenKey('myzip\shell\open\command', true);
  //用于打開.zzz文件的可執行程序
  reg.WriteString('', '"' + application.ExeName + '" "%1"');
  reg.CloseKey;
  reg.OpenKey('myzip\DefaultIcon',true);
  //取當前可執行程序的圖標爲.zzz文件的圖標
  reg.WriteString('',''+application.ExeName+',0');
  reg.Free;
  //立即刷新
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
  end;
  //壓縮文件
  procedure Tmyzip.ys_file(infileName, outfileName: string;password:pass;isjm:boolean;ysbz:integer);
  {
  infileName://需要壓縮加密的文件
  outfileName://壓縮加密後産生的文件
  password://解壓密碼
  ysbz://壓縮標准
  }
  var
  instream:TMemoryStream; //文件加密後的臨時流
  outStream: TFileStream; //壓縮輸出文件流
  begin
   //創建 [文件加密後的臨時流]
   instream:=TMemoryStream.Create;
   //文件加密
   jm_file(infileName,instream,password,isjm);
   //創建壓縮輸出文件流
   outStream := TFileStream.create(outFIleName, fmCreate);
   try
   //[文件加密後的臨時流] 壓縮
   ys_stream(instream,OutStream,ysbz);
   finally
   OutStream.free;
   instream.Free ;
   end;
  end;
  //解壓文件
  function Tmyzip.jy_file(infileName: string;password:pass=''):boolean;
  var
  inStream,inistream,filestream_ok: TFileStream;
  {
  instream://解壓文件名稱
  inistream://INI臨時文件流
  filestream_ok://解壓OK的文件
  }
  outStream:tmemorystream; //臨時內存流
  inifile:TINIFILE; //臨時INI文件
  FileSize:integer; //密碼文件的SIZE
  resultvalue:boolean;//返回值
  begin
  try
  inStream := TFileStream.create(inFIleName, fmOpenRead);
  try
   outStream := tmemorystream.create;
   try
   jy_stream(insTream,OutStream);
   //生成臨時INI文件
   inistream:=TFileStream.create(ExtractFilePath(paramstr(0))+'tmp.in_', fmCreate);
   try
   //指向存儲解碼信息的INTEGER型變量位置
   OutStream.Seek(-sizeof(FileSize),sofromend);
   //讀入變量信息
   OutStream.ReadBuffer(FileSize,sizeof(FileSize));
   //指向解碼信息位置
   OutStream.Seek(-(FileSize+sizeof(FileSize)),sofromend);
   //將解碼信息讀入INI流中
   inistream.CopyFrom(OutStream,FileSize);
   //釋放INI文件流
   inistream.Free ;
   //讀入INI文件信息
   inifile:=TINIFILE.Create(ExtractFilePath(paramstr(0))+'tmp.in_');
   resultvalue:=inifile.ReadBool('file1','isjm',false);
   if resultvalue then
   begin
   if inifile.ReadString ('file1','password','')=trim(password) then
   resultvalue:=true
   else
   resultvalue:=false;
   end
   else
   resultvalue:=true;
   if resultvalue then
   begin
   filestream_ok:=TFileStream.create(ExtractFilePath(paramstr(1))+inifile.ReadString('file1','filename','wnhoo.zzz'),fmCreate);
   try
   OutStream.Position :=0;
   filestream_ok.CopyFrom(OutStream,inifile.ReadInteger('file1','filesize',0));
   finally
   filestream_ok.Free ;
   end;
   end;
   inifile.Free;
   finally
   //刪除臨時INI文件
   deletefile(ExtractFilePath(paramstr(0))+'tmp.in_');
   end;
   //
   finally
   OutStream.free;
   end;
  finally
   inStream.free;
  end;
  except
  resultvalue:=false ;
  end;
  result:=resultvalue;
  end;
  //自解壓創建
  procedure tmyzip.zjywj(var filename:string);
  var
  myRes: TResourceStream;//臨時存放自解壓EXE文件
  myfile:tfilestream;//原文件流
  xfilename:string;//臨時文件名稱
  file_ok:tmemorystream; //生成文件的內存流
  filesize:integer; //原文件大小
  begin
  if FileExists(filename) then
  begin
  //創建內存流
  file_ok:=tmemorystream.Create ;
  //釋放資源文件-- 自解壓EXE文件
  myRes := TResourceStream.Create(Hinstance, 'myzjy', Pchar('exefile'));
  //將原文件讀入內存
  myfile:=tfilestream.Create(filename,fmOpenRead);
  try
  myres.Position:=0;
  file_ok.CopyFrom(myres,0);
  file_ok.Seek(0,sofromend);
  myfile.Position:=0;
  file_ok.CopyFrom(myfile,0);
  file_ok.Seek(0,sofromend);
  filesize:=myfile.Size;
  file_ok.WriteBuffer(filesize,sizeof(filesize));
  file_ok.Position:=0;
  xfilename:=ChangeFileExt(filename,'.exe') ;
  file_ok.SaveToFile(xfilename);
  finally
  myfile.Free ;
  myres.Free ;
  file_ok.Free ;
  end;
  DeleteFile(filename);
  filename:=xfilename;
  end;
  end;
  //#####################################################
  destructor Tmyzip.Destroy;
  begin
  inherited Destroy;
  end;
  end.
  3 、結束語
  Delphi的全新可視化編程環境,爲我們提供了一種方便、快捷的Windows應用程序開發工具。對于程序開發人員來講,使用Delphi開發應用軟件,無疑會大大地提高編程效率。在delphi中可以很方便的利用流實現文件處理、動態內存處理、網絡數據處理等多種數據形式,寫起程序也會大大提高效率的。
  參考文獻:
  1、DELPHI系統幫助
  2、馮志強. Delphi 中壓縮流和解壓流的應用
  3、陳經韬.談Delphi編程中「流」