Delphi中流类的学习(一)

最近不怎么忙,看了一下万一老师的delphi博客学习了一下delphi中的流类。写一下我对delphi流的总结已助以后参考。流就是一段数据或一块内存,在面向对象的编程语言像Java和C#等里面都有这个类,操作流时我们不用关心里面的数据是啥,只需知道流的当前位置和流的大小即可。下面重点说一下Delphi中的流类。

1.Delphi中流类的层次图

 

 

TStream类为所有流类的父类,该类为抽象类,提供了许多方法,主要属性为Position属性指明流中读写的当前偏移量,Size属性指明了以字节为单位的流的的大小,常用方法CopyFrom从Source所指定的流中拷贝Count个字节到当前流中并将指针从当前位置移动Count个字节数,函数返回值是实际拷贝的字节数,对流的操作, 不过就是读取和写入. 所以流最主要的方法就是 ReadWrite.

Seek方法将流的当前指针移动Offset个字节,字节移动的起点由Origin指定。如果Offset是负数,Seek方法将从所描述的起点往流的头部移动。其他流类均继承并扩张了TStream类,TFileStream对象是在磁盘文件上存储数据的Stream对象。TMemoryStream对象是一个管理动态内存中的数据的Stream对象。这两个流对象在实际用的较多,所以本文重点讲述这两个类。

2.流的读写应用

 用TFileStream读写实现带进度的文件复制

  新建应用程序,在窗体上放置一个button1,一个ProgressBar1,button控件单击事件如下:

procedure TForm2.cxButton5Click(Sender: TObject);
const
  getpath='E:/MXTC操作接口.doc';
  setpath='E:/test.doc';
var
  getstream,setstream:TFileStream;
  num,n:Integer;
  buf:PByte;
  bufsize,block:Integer;
begin
  if not FileExists(getpath) then
   begin
     ShowMessage('源文件不存在!');
     Exit;
   end;

  getstream:=TFileStream.Create(getPath,fmOpenRead or fmShareExclusive);
  setstream:=TFileStream.Create(setpath,fmCreate);

  num:=getstream.Size;
  setstream.Size:=num;
  getstream.Position:=0;
  setstream.Position:=0;

  bufsize:=num;  //bufsize记录流的总大小
  block:=bufsize div 100;  //block记录每块的大小
  GetMem(buf,bufsize);

  pb1.Max:=100;
  pb1.Min:=0;
  pb1.Position:=0;

  while num<>0 do
   begin
     Application.ProcessMessages;
     n:=block;
     if n>num then n:=num; //判断最后一个时, 有多少算多少
     getstream.Read(buf^,n);
     setstream.Write(buf^,n);
     pb1.Position:=Trunc((1-num/bufsize)*100);
     Dec(num,n);  //剩余大小
   end;

   FreeMem(buf,bufsize);
   getstream.Free;
   setstream.Free;

   ShowMessage('复制完毕!');
   pb1.Position:=0;
end;

 

 

用TCompressionStream和TDecompressionStream压缩和解压文件

 新建应用程序,在窗体上放置两个按钮,按钮事件分别如下:

procedure TForm2.btnCompressionClick(Sender: TObject);
var
  cs:TCompressionStream;
  fs,ms:TMemoryStream;
  num:Integer;
begin
  {第一步: 调入要压缩的文件, 并获取大小}
  fs:=TMemoryStream.Create;
  fs.LoadFromFile('E:/test.txt');
  num:=fs.Size;

  {第二步: 建立接收的流, 并先写入原始文件大小}
  ms:=TMemoryStream.Create;
  ms.Write(num,SizeOf(num));

   {第三步: 压缩}
  cs:=TCompressionStream.Create(clMax,ms);  //压缩比例最大化,ms为接受流
  fs.SaveToStream(cs);  //保存流到压缩流
  cs.Free;   {压缩流 Free 后才真正完成压缩, 所以提前 Free}
  ms.SaveToFile('E:/test.zipx');
  ms.Free;
  fs.Free;
end;

 

procedure TForm2.btnDecomClick(Sender: TObject);
 var
  ds: TDecompressionStream; {解压流}
  fs,ms: TMemoryStream;     {fs 是准备要解压的流; ms 是接受解压数据的流}
  num1: Integer;             {接受文件压缩前的大小}
begin
  {第一步: 准要解压的文件}
  fs := TMemoryStream.Create;
  fs.LoadFromFile('E:/test.zipx'); {必须是上一个压缩方法生成的文件}

  {第二步: 读出文件压缩前的大小}
  fs.Position := 0;
  fs.ReadBuffer(num1,SizeOf(num1));

  {第三步: 准备好要接收的流, 并设置需要的大小}
  ms := TMemoryStream.Create;
  ms.SetSize(num1);

  {第四步: 解压}
  ds := TDecompressionStream.Create(fs); {参数是要解压的流}

  {第五步: 把解压后的数据读出存放到已准备好接收的流}
  ds.Read(ms.Memory^, num1);

  {第六步: 保存}
  ms.SaveToFile('E:/test2.txt');

  ds.Free;
  ms.Free;
  fs.Free;
end;

流操作序列化和反序列化

  新建应用程序,窗体上放置两个button控件和一个memo控件,button控件单击事件代码如下:

procedure TForm1.btn7Click(Sender: TObject);  //流操作序列化
var
  stream:TStream;
const
  path='E:/m.dat';
begin
  stream:=TFileStream.Create(path,fmCreate);
  stream.WriteComponentRes(mmo2.ClassName,mmo2); //写入资源到文件
  stream.Free;
end;

 

procedure TForm1.btn8Click(Sender: TObject); //流操作反序列化
var
  stream:TStream;
const
  path='E:/m.dat';
begin
  stream:=TFileStream.Create(path,fmOpenRead);
  stream.ReadComponentRes(mmo2);  //读取资源到控件
  stream.Free;
end;

以上代码均出自万一的博客,如需详细学习资料可以查看http://del.cnblogs.com/,也希望有更多的人来交流。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页