《Mastering Delphi 6》学习笔记之十

    技术2022-05-11  112

    Delphi中的Serialiation 

     

    熟悉MFC的人对Serialize这个虚拟函数大概不会陌生。在MFC中,如果要用Serialization机制读取和保存数据,大概是这样:

    void CMyDoc::Serialize(CArchive& ar)

    {

      if (ar.IsStoring())

      {

    ar << myString;

    ar << myInt;

      }

      else

      {

    ar >> myString;

    ar >> myInt;

      }

    }

    Object Pascal中有没有类似的机制呢?接触到TReader和TWriter这两个类之后,我知道我找到答案了。

    不需多讲理论,来看一个实际的例子。在Form上面放三个Edit和两个Button,另外再加一个OpenDialog和SaveDialog。代码如下:

    procedure TForm1.Button1Click(Sender: TObject);

    begin

      if SaveDialog1.Execute then

         Serialize(SaveDialog1.FileName,True);

    end;

     

    procedure TForm1.Button2Click(Sender: TObject);

    begin

      if OpenDialog1.Execute then

         Serialize(OpenDialog1.FileName,False);

    end;

     

    procedure TForm1.Serialize(const FileName:string; bSave: Boolean);

    var

      Reader : TReader;

      Writer : TWriter;

      Stream : TFileStream;

    begin

      if bSave then begin

         Stream := TFileStream.Create(FileName,fmOpenWrite or fmCreate);

         Writer := TWriter.Create(Stream,4096);

         Writer.WriteString(Edit1.Text);

         Writer.WriteInteger(StrToInt(Edit2.Text));

         Writer.WriteFloat(StrToFloat(Edit3.Text));

         Writer.Free;

         Stream.Free;

      end  

      else begin

         Stream := TFileStream.Create(FileName,fmOpenRead);

         Reader := TReader.Create(Stream,4096);

         Edit1.Text := Reader.ReadString;

         Edit2.Text := IntToStr(Reader.ReadInteger);

         Edit3.Text := FloatToStr(Reader.ReadFloat);

         Reader.Free;

         Stream.Free;

      end;

    end;

    如果愿意的话,完全可以将Serialize包装成一个virtual method,从而让派生类中的实现更加简洁。

    TReader和TWriter不仅能够读取和写入Object Pascal中绝大部分标准数据类型,而且能够读写Collection/List/Variant这些高级类型,甚至能够读写Perperties和Component。不过,TReader/TWriter自身实际上提供的功能很有限,大部分实际的工作是由TStream这个非常强大的类来完成的。从TReader和TWriter的声明中可以看到一些特别为Component而设计的方法,不难猜想,Delphi开发环境本身很可能就是利用TReader/TWriter,将构件的属性写入.DFM文件以及从.DFM文件中读取属性值的。

    下面的例子很有用也非常有趣,它的效果完全相当于Form Designer中的View As Text命令:

    var

      DFMBuf, TextBuf : TStream;

    begin

      DFMBuf := TMemoryStream.Create;

      DFMBuf.WriteComponent(Self);

      TextBuf := TMemoryStream.Create;

      DFMBuf.Seek(0,soFromBeginning);

      ObjectBinaryToText(DFMBuf,TextBuf);

      TextBuf.Seek(0,soFromBeginning);

      Memo1.Lines.LoadFromStream(TextBuf);

      TextBuf.Free;

      DFMBuf.Free;

     

    甚至可以从可执行文件中读取Form的信息:

    var

      DFMBuf, TextBuf : TStream;

      buf : pointer;

    begin

      DFMBuf := TResourceStream.Create(HInstance,'TForm1',RT_RCDATA);

      DFMBuf.Position := 0;

      TextBuf := TMemoryStream.Create;

      DFMBuf.Seek(0,soFromBeginning);

      ObjectBinaryToText(DFMBuf,TextBuf);

      TextBuf.Seek(0,soFromBeginning);

      Memo1.Lines.LoadFromStream(TextBuf);

      TextBuf.Free;

      DFMBuf.Free;

    end;

    (说明:如果窗体不是TForm1,那么请将TResourceStream.Create一句中的第二个参数改为相应的窗体类名。)

    好好读懂这些代码,相信自己做一个DFM Viewer也不是遥不可及的事情了吧!

     


    最新回复(0)