Delphi 中流的使用

所谓"流", 就是一段数据或是一块内存;
在进行流操作时, 我们不必关心流中的数据到底是什么; 只需要知道流的大小和当前的指针位置. 所以流只有两个属性:
Size、Position.
对流的操作, 不过就是读取和写入. 所以流最主要的方法就是 Read 和 Write.
在很多控件的使用中, 读取主要用 LoadFromStream; 写入主要用 SaveToStream.

 

TMemoryStream(内存流) 入门
举个例子: (建立新工程, 添加两个 Memo、两个 Button)

unit Unit1;

interface

uses 

    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;

type 

   TForm1 =class(TForm)   

        Memo1: TMemo;   

        Memo2: TMemo; 

        Button1: TButton;   

        Button2: TButton;   

       procedure FormCreate(Sender: TObject);   

       procedure Button1Click(Sender: TObject);   

       procedure Button2Click(Sender: TObject);   

       procedure FormDestroy(Sender: TObject); 

end;

var 

    Form1: TForm1;

implementation

{$R *.dfm}

var 

     mStream: TStream;

{声明一个流对象}

procedure TForm1.FormCreate(Sender: TObject);

begin 

     mStream := TMemoryStream.Create; {TStream 是抽象类, 只能通过其子类实例化; 这里我们用了内存流来生成实例} 

     Memo1.Lines.Text :='ABCDEFGHIJKLMNOPQRSTUVWXYZ'{给 Memo1 个初始值}

end;

procedure TForm1.Button1Click(Sender: TObject);

begin 

     Memo1.Lines.SaveToStream(mStream);     {把 Memo1 中的内容写入到流} 

     ShowMessage(IntToStr(mStream.Size));   {26, 当前流的大小} 

     ShowMessage(IntToStr(mStream.Position));{26, 当前流的指针}

end;

procedure TForm1.Button2Click(Sender: TObject);

begin 

   mStream.Position :=4;             {调整流的当前指针位置} 

   Memo2.Lines.LoadFromStream(mStream);

{读出流中的内容到 Memo2} {    现在 Memo2 中的内容应该是: EFGHIJKLMNOPQRSTUVWXYZ    如果 Position 是 0,  memo2 读出的内容会是: ABCDEFGHIJKLMNOPQRSTUVWXYZ    如果 Position 等于 Size, 在这里如果是 26, Memo2 就读不出什么了.  }

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin 

    mStream.Free;{流释放时, 所用内存当然也会同时释放}

end;

end.

 

内存流读取文件

unit Unit1;

interface

uses 

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;

type 

TForm1 = class(TForm)   

     Memo1: TMemo;   

     Button1: TButton;   

     Button2: TButton;   

     Button3: TButton;   

     procedure FormCreate(Sender: TObject);   

     procedure FormDestroy(Sender: TObject);   

     procedure Button1Click(Sender: TObject);   

     procedure Button2Click(Sender: TObject);   

     procedure Button3Click(Sender: TObject); 

end;

var 

     Form1: TForm1;

implementation{$R *.dfm}

var 

     mStream: TMemoryStream;

procedure TForm1.FormCreate(Sender: TObject);//程序开始先创建一个准备要测试的文件

var 

     strList: TStringList;

begin 

    strList := TStringList.Create; 

    strList.Add('aaaaaaaa'); 

    strList.Add('bbbbbbbb'); 

    strList.Add('cccccccc'); 

    strList.Add('dddddddd'); 

    strList.SaveToFile('c:\temp\test.txt'); 

    strList.Free;  {同时建立内存流} 

    mStream := TMemoryStream.Create;

end;

procedure TForm1.Button1Click(Sender: TObject);//通过流读文件到 Memo

begin 

     mStream.LoadFromFile('c:\temp\test.txt');{把文件读入内存流} 

     Memo1.Lines.LoadFromStream(mStream);     {把内存流载入 Memo1}

end;

procedure TForm1.Button2Click(Sender: TObject);//用字符指针读取流中的内容

var 

    pc: PChar;

begin 

    pc := mStream.Memory;{把字符指针指向内存流} 

    ShowMessage(pc[0]); {a; 第一个字符} 

    ShowMessage(pc[10]); {b; 这个第二行的第一个字符; 每行8个字再加换行与回车共10个字符} 

    ShowMessage(pc[20]); {c}  ShowMessage(pc[30]); {d}

end;

procedure TForm1.Button3Click(Sender: TObject);//从流读入到缓冲区

var 

    buffer: array[0..2]of Char;{定义个字符缓冲区}

begin 

    mStream.Seek(0, soFromBeginning); 

    mStream.Read(buffer, SizeOf(buffer)); 

    ShowMessage(buffer);{aaa} 

    mStream.Seek(10, soFromBeginning); 

    mStream.Read(buffer, SizeOf(buffer)); 

    ShowMessage(buffer); {bbb} 

    mStream.Seek(20, soFromBeginning); 

    mStream.Read(buffer, SizeOf(buffer)); 

    ShowMessage(buffer); {ccc} 

    mStream.Seek(30, soFromBeginning); 

    mStream.Read(buffer, SizeOf(buffer)); 

    ShowMessage(buffer); {ddd}

{关于 Seek 函数:  参数1: Offset 是偏移量;  参数2: Origin 是指针的基准位置, 有三个选值: soFromBeginning、soFromCurrent、soFromEnd        soFromBeginning: 以开始为基准, 此时参数 Offset 要 >= 0;        soFromCurrent: 以当前位置为基准;        soFromEnd: 以结束为基准; 此时参数 Offset 要 <= 0;  返回: 指针新位置}

end;

procedure TForm1.FormDestroy(Sender: TObject);

begin 

    mStream.Free;

end;

end.

 

TFileStream读写

TStream 是一个抽象的基类, 不能直接生成对象. 在具体的应用中, 主要使用它的子孙类:

TFileStream: 文件流

TStringStream: 字符串流

TMemoryStream: 内存流

TResourceStream: 资源文件流

THandleStream: 是 TFileStream 的父类、

TStream 的子类TCustomMemoryStream: 是 TMemoryStream 和 TResourceStream 的父类、

TStream 的子类与流相关的常用类还有: TReader、TWriter、TCompressionStream、TDecompressionStream

来一个文件流的例子:

procedure TForm1.Button1Click(Sender: TObject);

var 

    getStream,setStream: TFileStream; {声明一个文件流} 

    getPath,setPath:string;

begin 

     getPath := 'c:\temp\get.jpg';{需要这个文件存在} 

     setPath :='c:\temp\set.jpg';{这个会自动建立} 

     ifnot FileExists(getPath)then 

     begin   

         ShowMessage('找不到我们要测试的图片文件: ' + getPath);   

         Exit;

      end

      getStream := TFileStream.Create(getPath, fmOpenReador fmShareExclusive); 

      setStream := TFileStream.Create(setPath, fmCreate); {建立文件流需要两个参数: 参数 1 是路径, 参数 2 是打开模式} 

      getStream.Position :=0;{流指针移到开始, 复制时从这里开始} 

      setStream.CopyFrom(getStream, getStream.Size);{Copy 流} {CopyFrom 的参数 2 是要复制的内容大小; 如果为 0 , 不管指针在什么位置都会复制所有内容} {CopyFrom 返回实际拷贝的字节数}

{这时硬盘上就有 set.jpg 文件, 与 get.jpg 一么一样} {其实就是复制文件, 不过这里我们是用文件流实现的} 

     getStream.Free; 

     setStream.Free;

end;

TFileStream 打开模式与共享模式:

分类参数说明



fmCreate 建立文件, 如果存在则打开它。
fmOpenRead只读打开
fmOpenWrite只写打开
fmOpenReadWrite读写打开



fmShareCompat共享模式, 兼容 Dos
fmShareExclusive 不允许别人以任何方式打开
fmShareDenyWrite 允许别人以只写方式打开
fmShareDenyRead允许别人以只读方式打开
fmShareDenyNone允许别人以任何方式打开

 

遍历读取流中的所有数据
unit Unit1;
interface
uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;
type 
    TForm1 = class(TForm)   
        Memo1: TMemo;   
        Memo2: TMemo;{需要添加两个 Memo 用于显示}   
        Button1: TButton;   
        procedure Button1Click(Sender: TObject);   
        procedure FormCreate(Sender: TObject); 
    end;
var 
    Form1: TForm1;
implementation
{ $R *.dfm} //先制造一个测试文件
procedure TForm1.FormCreate(Sender: TObject);
var 
    strList: TStringList;
begin 
    strList := TStringList.Create; 
    strList.Add('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); 
    strList.SaveToFile('c:\temp\test.txt');  strList.Free;
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var 
     ms: TMemoryStream; 
     c: Char;  s1,s2: string;
begin 
     ms := TMemoryStream.Create; 
     ms.LoadFromFile( 'c:\temp\test.txt' ); {读入内存流}  
     s1 := '' ;  s2 := ''
     ms.Position := 0 ;                      {指针到开始}  
     while ms.Position < ms.Size do          {循环读出}  
     begin   
         ms.Read(c, 1 );                        {每读出一个字节, 指针会自动移到新的位置}    
         s1 := s1 + c + ' ' ;                  {用文本记录}    
         s2 := s2 + IntToHex(Byte(c), 2 ) + ' ' ; {用两位数的十六进制记录}  
     end
     Memo1.Lines.Text := s1; 
     Memo2.Lines.Text := s2;  {Memo1 会显示: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z }   {Memo2 会显示: 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 0D 0A}  
     ms.Free;
end;
end.
 
序列化
unit Unit1;
interface
uses 
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;
type 
     TForm1 = class(TForm)   
          Button1: TButton;   
          Button2: TButton;   
          Button3: TButton;   
          Button4: TButton;   
          Memo1: TMemo;   
          procedure Button1Click(Sender: TObject);   
          procedure Button2Click(Sender: TObject); 
           procedure Button3Click(Sender: TObject); 
           procedure Button4Click(Sender: TObject); 
     private    { Private declarations }  
     public    { Public declarations }  
end;
var 
     Form1: TForm1;
implementation
{$R *.dfm} //添加一个 Memo1 然后修改其内容
procedure TForm1.Button1Click(Sender: TObject);
begin 
     WriteComponentResFile( 'c:\temp\memo.dat' , Memo1);  {只此一句就可以把当前的 Memo 的状态序列化到文件}
end;
//反序列化, 读回
procedure TForm1.Button2Click(Sender: TObject);
begin 
     ReadComponentResFile( 'c:\temp\memo.dat' , Memo1);  {一句话就可以读回, 不管是经过了什么操作(甚至是关机)}
end; {  这好像和流没什么关系, 其实这就是流的典型操作,  WriteComponentResFile 和 ReadComponentResFile 分别调用了流类的  WriteComponentRes 与 ReadComponentRes 方法.  下面用更直接的流的方式重新实现一次:}
//序列化
procedure TForm1.Button3Click(Sender: TObject);
var 
     stream: TStream;
     const  strPath ='c:\temp\m.dat';
begin 
     stream := TFileStream.Create(strPath, fmCreate); 
     stream.WriteComponentRes(Memo1.ClassName, Memo1); {WriteComponentRes 有两个参数: 文件名和组件名} 
     stream.Free;
end;
//反序列化
procedure TForm1.Button4Click(Sender: TObject);
v ar 
     stream: TStream;
     const  strPath = 'c:\temp\m.dat' ;
begin 
     stream := TFileStream.Create(strPath, fmOpenRead); 
     stream.ReadComponentRes(Memo1);  {ReadComponentRes 只有一个参数: 组件名}  
     stream.Free;
end;
end.
 
用流读写结构化文件
unit Unit1;
interface
uses 
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;
type 
     TForm1 = class(TForm)   
           Memo1: TMemo;    {添加 Memo 显示内容}    
          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}
type 
      TRec = record    {定义一个记录}    
           name: string[ 8 ];   
           age: Word; 
      end; //写入
procedure TForm1.Button1Click(Sender: TObject);
var 
     rec: TRec; 
     ms: TMemoryStream;
begin 
     ms := TMemoryStream.Create; 
     rec.name := '张三' ;
     rec.age := 8
     ms.Write(rec, SizeOf(rec)); 
     rec.name := '李四' ;
     rec.age := 81
     ms.Write(rec, SizeOf(rec)); 
     rec.name := '王二麻子' ;
     rec.age := 18
     ms.Write(rec, SizeOf(rec)); 
     ms.SaveToFile( 'c:\temp\rec.dat' ); 
     ms.Free;
end;
//读取
procedure TForm1.Button2Click(Sender: TObject);
var 
    rec: TRec; 
    ms: TMemoryStream;
begin 
    ms := TMemoryStream.Create; 
    ms.LoadFromFile( 'c:\temp\rec.dat' ); 
    Memo1.Clear; 
    ms.Position := 0
    while ms.Position < ms.Size do 
    begin   
         ms.Read(rec, SizeOf(rec));   
         Memo1.Lines.Add(rec.name + ' ' + IntToStr(rec.age)); 
    end{Memo1 的显示结果会是:    张三 8    李四 81    王二麻子 18  }  
    ms.Free;
end;
end.
 
压缩与解压缩
unit Unit1;
interface
uses 
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;
type 
      TForm1 = class(TForm)   
           Button1: TButton;   
           Button2: TButton; 
           procedure Button1Click(Sender: TObject);   
           procedure Button2Click(Sender: TObject); 
      end;
v ar 
     Form1: TForm1;
implementation
{$R *.dfm}
uses
     Zlib; {压缩流 TCompressionStream 与解压缩流 TDecompressionStream 来自 Zlib 单元} //压缩
procedure TForm1.Button1Click(Sender: TObject);
var 
     cs: TCompressionStream; {定义压缩流}  
     fs,ms: TMemoryStream;  {fs 是要压缩的流; ms 是接收压缩后文件的流}  
     num: Integer;          {原始文件大小}
begin  {第一步: 调入要压缩的文件, 并获取大小}  
      fs := TMemoryStream.Create; 
      fs.LoadFromFile( 'c:\temp\test.txt' ); {文件要存在啊}  
      num := fs.Size;  {第二步: 建立接收的流, 并先写入原始文件大小}  
      ms := TMemoryStream.Create; 
      ms.Write(num, SizeOf(num));  {第三步: 压缩}
      cs := TCompressionStream.Create(clMax, ms); {参数1是压缩比; 参数2是接收流}  
      fs.SaveToStream(cs); {传入要压缩的数据}
      cs.Free;            {压缩流 Free 后才真正完成压缩, 所以提前 Free}   {第四步: 保存}  
      ms.SaveToFile( 'c:\temp\test.zipx' );  {第五步: 释放}  
      ms.Free;  fs.Free; {压缩比参数:  clNone    无压缩  clFastest 快速  clDefault 默认  clMax    最大比例}
end;
//解压缩
procedure TForm1.Button2Click(Sender: TObject);
var 
     ds: TDecompressionStream; {解压流}  
     fs,ms: TMemoryStream;    {fs 是准备要解压的流; ms 是接受解压数据的流}  
     num: Integer;            {接受文件压缩前的大小}
begin  {第一步: 准要解压的文件}  
     fs := TMemoryStream.Create; 
     fs.LoadFromFile( 'c:\temp\test.zipx' ); {必须是上一个压缩方法生成的文件}   {第二步: 读出文件压缩前的大小}  
     fs.Position := 0 ;  fs.ReadBuffer(num,SizeOf(num));  {第三步: 准备好要接收的流, 并设置需要的大小}  
     ms := TMemoryStream.Create;  ms.SetSize(num);  {第四步: 解压}  
     ds := TDecompressionStream.Create(fs); {参数是要解压的流}   {第五步: 把解压后的数据读出存放到已准备好接收的流}  
     ds.Read(ms.Memory^, num);  {第六步: 保存}  
     ms.SaveToFile( 'c:\temp\test2.txt' ); 
     ds.Free; 
     ms.Free; 
     fs.Free;
end;
end.
 
压缩与解压缩的函数
unit Unit1;
interface
uses 
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;
t ype 
      TForm1 = class(TForm)   
           Button1: TButton;   
           Button2: TButton;   
           procedure Button1Click(Sender: TObject);   
           procedure Button2Click(Sender: TObject);
       end;
var 
     Form1: TForm1;
implementation
{$R *.dfm}
uses
     Zlib; //压缩函数
procedure Zip( var fs: TMemoryStream);
var 
     cs: TCompressionStream; 
     ms: TMemoryStream; 
     num: Integer;
begin
      if not(Assigned(fs) and (fs.Size> 0 )) then
         Exit;   
     num := fs.Size;   
     ms := TMemoryStream.Create;   
     cs := TCompressionStream.Create(clMax, ms); 
     try   
         fs.SaveToStream(cs);   
         cs.Free;    //ms.Position := 0;  
         fs.Clear;   
         fs.WriteBuffer(num, sizeof(num));   
         fs.CopyFrom(ms, 0 ); 
     finally   
        ms.Free; 
     end;
end;
//解压函数
procedure UnZip( var fs: Tmemorystream);
var 
     ds: TDecompressionStream; 
     ms: TMemoryStream; 
     num: Integer;
begin
      if not(Assigned(fs) and (fs.Size> 0 )) then
        Exit; 
     fs.Position := 0
     fs.ReadBuffer(num,sizeof(num)); 
     ms := TMemoryStream.Create; 
     ds := TDecompressionStream.Create(fs); 
     try   
         ms.SetSize(num);   
         ds.Read(ms.Memory^, num);    //ms.Position := 0;    
         fs.Clear;   
         fs.CopyFrom(ms, 0 );
     finally   
         ds.Free;   
         ms.Free; 
     end;
end;
//压缩测试
procedure TForm1.Button1Click(Sender: TObject);
var 
      ms: TMemoryStream;
begin 
     ms := TMemoryStream.Create; 
     ms.LoadFromFile( 'c:\temp\test.txt' ); 
     Zip(ms); 
     ms.SaveToFile( 'c:\temp\test.zipx' );
end;
//解压测试
procedure TForm1.Button2Click(Sender: TObject);
var 
     ms: TMemoryStream;
begin 
     ms := TMemoryStream.Create; 
     ms.LoadFromFile( 'c:\temp\test.zipx' ); 
     UnZip(ms); 
     ms.SaveToFile( 'c:\temp\test2.txt' );
end;
end.
 
分割与合并文件函数
unit Unit1;
interface
uses 
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;
type 
     TForm1 = class(TForm)   
          Button1: TButton;   
          Button2: TButton;   
          procedure Button1Click(Sender: TObject);   
          procedure Button2Click(Sender: TObject); 
      end;
var 
     Form1: TForm1;
implementation
{$R *.dfm} //分割文件的函数 {参数 1 是要分割的文件名; 参数 2 是要风格文件的大小, 单位是 KB} {分割后的文件名扩展名用序号替换}
function SplitFile( const FileName: string; Size: Cardinal): Boolean;
var 
     fStream: TFileStream;   {原始文件}  
     toStream: TMemoryStream; {分文件}  
     p,i: Integer;            {p 记录当前指针位置; i 记录这是第几个分的文件}
begin 
     Result := False; 
     Size := Size * 1024 ;    {把大小的单位转换为字节}  
     fStream := TFileStream.Create(FileName, fmOpenRead); 
     p := 0
     i := 0
     toStream := TMemoryStream.Create; 
     while p < fStream.Size do
      begin   
          toStream.Clear;        {清空上次数据}    
          fStream.Position := p; {放好指针位置}  
           if fStream.Size-p < Size then
             Size := fStream.Size-p; {最后一个时, 有多少算多少}    
          toStream.CopyFrom(fStream, Size); {复制}    
          toStream.SaveToFile(FileName + '.' + IntToStr(i));        {保存}    
          Inc(i);   
          p := p + Size;
       end
      fStream.Free; 
      toStream.Free; 
      Result := True;
end;
//合并文件, 参数是其中一个分文件名
function MergeFile( const FileName: string): Boolean;
var 
     ms: TMemoryStream; {读取分文件}  
     fs: TFileStream;  {合并后的文件}  
     path: string
     i: Integer;
begin 
     path := ChangeFileExt(FileName, '' ); {去掉序号扩展名}  
     ShowMessage(path); 
     i := 0
     ms := TMemoryStream.Create; 
     fs := TFileStream.Create(path, fmCreate); 
     while FileExists(path + '.' + IntToStr(i)) do 
     begin   
          ms.LoadFromFile(path + '.' + IntToStr(i));   
          fs.CopyFrom(ms, 0 ); {TFileStream 不需要 SetSize; 但如果用 TMemoryStream 就需要}    
          Inc(i); 
     end
     ms.Free; 
     fs.Free;
end;
//测试分割
procedure TForm1.Button1Click(Sender: TObject);
begin 
     SplitFile( 'c:\temp\test.txt' , 10 );
end;
//测试合并
procedure TForm1.Button2Click(Sender: TObject);
begin 
     MergeFile( 'c:\temp\test.txt.0' );
end;
end.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值