Stream 对象,又称流式对象,是 TStream 、 THandleStream 、 TFileStream 、 TMemoryStream 、 TResourceStream 和 TBlobStream 等的统称。它们分别代表了在各种媒介上存储数据的能力,它们将各种数据类型 ( 包括对象和部件 ) 

在内存、外存和数据库字段中的管理操作抽象为对象方法,并且充分利用了面向对象技术的优点,应用程序可以相当容易地在各种 Stream 对象中拷贝数据。

  下面介绍各种对象的数据和方法及使用方法。

 

TStream 对象

 

   TStream 对象是能在各种媒介中存储二进制数据的对象的抽象对象。从 TStream 对象继承的对象用于在内存、 Windows 资源文件、磁盘文件和数据库字段等媒介中存储数据。

  Stream 中定义了两个属性: Size 和 Position 。它们分别以字节为单位表示的流的大小和当前指针位置。 TStream 中定义的方法用于在各种流中读、写和相互拷贝二进制数据。因为所有的 Stream 对象都是从 TStream 中继承来的,所以在 TStream 中定义的域和方法都能被 Stream 对象调用和访

问。此外,又由于面向对象技术的动态联编功能, TStream 为各种流的应用提供了统一的接口,简化了流的使用;不同 Stream 对象是抽象了对不同存储媒介的数据上的操作,因此, TStream 的需方法为在不同媒介间的数据拷贝提供了最简捷的手段。

 

TStream 的属性和方法

 

   1. Position 属性 

     声明: property Position: Longint; 

   Position 属性指明流中读写的当前偏移量。

   2. Size 属性

  声明: property Size: Longint; 

     Size 属性指明了以字节为单位的流的的大小,它是只读的。

   3. CopyFrom 方法

  声明: function CopyFrom(Source: TStream; Count: Longint): Longint; 

     CopyFrom 从 Source 所指定的流中拷贝 Count 个字节到当前流中, 并将指针从当前位置移动 Count 个字节数,函数返回值是实际拷贝的字节数。

   4. Read 方法

  声明: function Read(var Buffer; Count: Longint): Longint; virtual; abstract; 

     Read 方法从当前流中的当前位置起将 Count 个字节的内容复制到 Buffer 中,并把当前指针向后移动 Count 个字节数,函数返回值是实际读的字节数。如果返回值小于 Count ,这意味着读操作在读满所需字节数前指针已经到达了流的尾部。

   Read 方法是抽象方法。每个后继 Stream 对象都要根据自己特有的有关特定存储媒介的读操作覆盖该方法。而且流的所有其它的读数据的方法(如: ReadBuffer , ReadComponent 等)在完成实际的读操作时都调用了 Read 方法。面向对象的动态联编的优点就体现在这儿。因为后继 Stream 对

象只需覆盖 Read 方法,而其它读操作 ( 如 ReadBuffer 、 ReadComponent 等 ) 都不需要重新定义,而且 TStream 还提供了统一的接口。

   5. ReadBuffer 方法

  声明: procedure ReadBuffer(var Buffer; Count: Longint); 

   ReadBuffer 方法从流中将 Count 个字节复制到 Buffer 中, 并将流的当前指针向后移动 Count 个字节。如读操作超过流的尾部, ReadBuffer 方法引起 EReadError 异常事件。

   6. ReadComponent 方法

  声明: function ReadComponent(Instance: TComponent): TComponent; 

     ReadComponent 方法从当前流中读取由 Instance 所指定的部件,函数返回所读的部件。 ReadComponent 在读 Instance 及其拥有的所有对象时创建了一个 Reader 对象并调用它的 ReadRootComponent 方法。

  如果 Instance 为 nil , ReadComponent 的方法基于流中描述的部件类型信息创建部件,并返回新创建的部件。

   7. ReadComponentRes 方法

  声明: function ReadComponentRes(Instance: TComponent): TComponent; 

     ReadComponentRes 方法从流中读取 Instance 指定的部件,但是流的当前位置必须是由 WriteComponentRes 方法所写入的部件的位置。

   ReadComponentRes 

首先调用 ReadResHeader 方法从流中读取资源头,然后调用 ReadComponent 方法读取 Instance 。如果流的当前位置不包含一个资源头。 ReadResHeader 将引发一个 EInvalidImage 异常事件。在 Classes 库单元中也包含一个名为 ReadComponentRes 的函数,该函数执行相同的操作,只不过它基于应

用程序包含的资源建立自己的流。

   8. ReadResHeader 方法

  声明: procedure ReadResHeader; 

     ReadResHeader 方法从流的当前位置读取 Windows 资源文件头,并将流的当前位置指针移到该文件头的尾部。如果流不包含一个有效的资源文件头, ReadResHeader 将引发一个 EInvalidImage 异常事件。

  流的 ReadComponentRes 方法在从资源文件中读取部件之前,会自动调用 ReadResHeader 方法,因此,通常程序员通常不需要自己调用它。

   9. Seek 方法

  声明: function Seek(Offset: Longint; Origin: Word): Longint; virtual; abstract; 

     Seek 方法将流的当前指针移动 Offset 个字节,字节移动的起点由 Origin 指定。如果 Offset 是负数, Seek 方法将从所描述的起点往流的头部移动。下表中列出了 Origin 的不同取值和它们的含义:

 

                           函数 Seek 的参数的取值

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  常量       值       Seek 的起点          Offset 的取值

   ─────────────────────────────────

  SoFromBeginning     0            流的开头               正 数

  SoFromCurrent       1              流的当前位置         正数或负数   

  SoFromEnd          2              流的结尾               负 数

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

                   

     10. Write 方法

  在 Delphi 对象式管理的对象中有两类对象的方法都有称为 Write 的: Stream 对象和 Filer 对象。 Stream 对象的 Write 方法将数据写进流中。 Filer 对象通过相关的流传递数据,在后文中会介绍这类方法。

   Stream 对象的 Write 方法声明如下:

 

       function Write(const Buffer; Count: Longint): Longint; virtual; abstract; 

 

     Write 方法将 Buffer 中的 Count 个字节写入流中,并将当前位置指针向流的尾部移动 Count 个字节,函数返回写入的字节数。

     TStream 的 Write 方法是抽象的,每个继承的 Stream 对象都要通过覆盖该方法来提供向特定存储媒介 ( 内存、磁盘文件等 ) 写数据的特定方法。流的其它所有写数据的方法 ( 如 WriteBuffer 、 WriteComponent) 都调用 Write 担当实际的写操作。

   11. WriteBuffer 方法

  声明: procedure WriteBuffer(const Buffer; Count: Longint); 

   WriteBuffer 的功能与 Write 相似。 WriteBuffer 方法调用 Write 来执行实际的写操作,如果流没能写所有字节, WriteBuffer 会触发一个 EWriteError 异常事件。

   12. WriteComponent 方法

  在 Stream 对象和 Filer 对象都有被称为 WriteComponent 的方法。 Stream 对象的 WriteComponent 方法将 Instance 所指定的部件和它所包含的所有部件都写入流中; Writer 对象的 WriteComponent 将指定部件的属性值写入 Writer 对象的流中。

   Stream 对象的 WriteComponent 方法声明是这样的:

        procedure WriteComponent(Instance: Tcomponent); 

 

   WriteComponent 创建一个 Writer 对象,并调用 Writer 的 WriteRootComponent 方法将 Instance 及其拥有的对象写入流。

   13. WriteComponentRes 方法

  声明: WriteComponentRes(const ResName: String; Instance: TComponent); 

   WriteComponentRes 方法首先往流中写入标准 Windows 资源文件头,然后将 Instance 指定的部件写入流中。要读由 WriteComponentRes 写入的部件,必须调用 ReadComponentRes 方法。

   WriteComponentRes 使用 ResName 传入的字符串作为资源文件头的资源名,然后调用 WriteComponent 方法将 Instance 和它拥有的部件写入流。

   14. WriteDescendant 方法

  声明: procedure WriteDescendant(Instance Ancestor: TComponent); 

   Stream 对象的 WriteDescendant 方法创建一个 Writer 对象,然后调入该对象的 WriteDescendant 方法将 Instance 部件写入流中。 Instance 可以是从 Ancestor 部件继承的窗体,也可以是在从祖先窗体中继承的窗体中相应于祖先窗体中 Ancestor 部件的部件。

   15. WriteDescendantRes 方法

  声明: procedure WriteDescendantRes(const ResName: String;

                                         Instance, Ancestor: TComponent);

   WriteDescendantRes 方法将 Windows 资源文件头写入流,并使用 ResName 作用资源名,然后调用 WriteDescendant 方法,将 Instance 写入流。

 

TStream 的实现原理

 

   TStream 对象是 Stream 对象的基础类,这是 Stream 对象的基础。为了能在不同媒介上的存储数据对象,后继的 Stream 对象主要是在 Read 和 Write 方法上做了改进,。因此,了解 TStream 是掌握 Stream 对象管理的核心。 Borland 公司虽然提供了 Stream 对象的接口说明文档,但对于其实现和应

用方法却没有提及,笔者是从 Borland Delphi 2.0 Client/Server Suite 提供的源代码和部分例子程序中掌握了流式对象技术。

  下面就从 TStream 的属性和方法的实现开始。

   1. TStream 属性的实现

  前面介绍过, TStream 具有 Position 和 Size 两个属性,作为抽象数据类型,它抽象了在各种存储媒介中读写数据所需要经常访问的域。那么它们是怎样实现的呢?

  在自定义部件编写这一章中介绍过部件属性定义中的读写控制。 Position 和 Size 也作了读写控制。定义如下:

 

     property Position: Longint read GetPosition write SetPosition;

     property Size: Longint read GetSize;

 

  由上可知, Position 是可读写属性,而 Size 是只读的。

   Position 属性的实现就体现在 GetPosition 和 SetPosition 。当在程序运行过程中,任何读取 Position 的值和给 Position 赋值的操作都会自动触发私有方法 GetPosition 和 SetPosition 。两个方法的声明如下:

 

     function TStream.GetPosition: Longint;

     begin

       Result := Seek(0, 1);

     end;

 

     procedure TStream.SetPosition(Pos: Longint);

     begin

       Seek(Pos, 0);

     end;

 

     在设置位置时, Delphi 编译机制会自动将 Position 传为 Pos 。

  前面介绍过 Seek 的使用方法,第一参数是移动偏移量,第二个参数是移动的起点,返回值是移动后的指针位置。

   Size 属性的实现只有读控制,完全屏蔽了写操作。读控制方法 GetSize 实现如下:

 

     function TStream.GetSize: Longint;

     var

       Pos: Longint;

     begin

       Pos := Seek(0, 1);

       Result := Seek(0, 2);

       Seek(Pos, 0);

     end;

 

     2. TStream 方法的实现

  ⑴ CopyFrom 方法

   CopyFrom 是 Stream 对象中很有用的方法,它用于在不同存储媒介中拷贝数据。例如,内存与外部文件之间、内存与数据库字段之间等。它简化了许多内存分配、文件打开和读写等的细节,将所有拷贝操作都统一到 Stream 对象上。

  前面曾介绍: CopyFrom 方法带 Source 和 Count 两个参数并返回长整型。该方法将 Count 个字节的内容从 Source 拷贝到当前流中,如果 Count 值为 0 则拷贝所有数据。

 

     function TStream.CopyFrom(Source: TStream; Count: Longint): Longint;

     const

       MaxBufSize = $F000;

     var

       BufSize, N: Integer;

       Buffer: PChar;

     begin

       if Count = 0 then

       begin

         Source.Position := 0;

         Count := Source.Size;

       end;

       Result := Count;

       if Count > MaxBufSize then BufSize := MaxBufSize else BufSize := Count;

       GetMem(Buffer, BufSize);

       try

         while Count <> 0 do

         begin

           if Count > BufSize then 

             N := BufSize 

           else

              N := Count;

           Source.ReadBuffer(Buffer^, N);

           WriteBuffer(Buffer^, N);

           Dec(Count, N);

         end;

       finally

         FreeMem(Buffer, BufSize);

       end;

     end;

 

  ⑵ ReadBuffer 方法和 WriteBuffer 方法

   ReadBuffer 方法和 WriteBuffer 方法简单地调用虚拟函数 Read 、 Write 来读写流中数据,它比 Read 和 Write 增加了读写数据出错时的异常处理。

 

     procedure TStream.ReadBuffer(var Buffer; Count: Longint);

     begin

       if (Count <> 0) and (Read(Buffer, Count) <> Count) then

         raise EReadError.CreateRes(SReadError);

     end;

 

     procedure TStream.WriteBuffer(const Buffer; Count: Longint);

     begin

       if (Count <> 0) and (Write(Buffer, Count) <> Count) then

         raise EWriteError.CreateRes(SWriteError);

     end;

 

  ⑶ ReadComponent 、 ReadResHeader 和 ReadComponentRes 方法

   ReadComponent 方法从当前流中读取部件。在实现上 ReadComponent 方法创建了一个 TStream 对象,并用 TReader 的 ReadRootComponent 方法读部件。在 Delphi 对象式管理中, Stream 对象和 Filer 对象结合很紧密。 Stream 对象的许多方法的实现需要 Filer 对象的支持,而 Filer 对象的构造函数

直接就以 Stream 对象为参数。在 ReadComponent 方法的实现中就可清楚地看到这一点:

 

     function TStream.ReadComponent(Instance: TComponent): TComponent;

     var

       Reader: TReader;

     begin

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

       try

         Result := Reader.ReadRootComponent(Instance);

       finally

          Reader.Free;

       end;

     end;

 

     ReadResHeader 方法用于读取 Windows 资源文件的文件头,由 ReadComponentRes 方法在读取 Windows 资源文件中的部件时调用,通常程序员不需自己调用。如果读取的不是资源文件 ReadResH := FSize + Offset;

           end;

           Result := FPosition;

         end;

 

   Offse 代表移动的偏移量。 Origin 代表移动的起点,值为 0 表示从文件头开始,值为 1 表示从当前位置开始,值为 2 表示从文件尾往前,这时 OffSet 一般为负数。 Seek 的实现没有越界的判断。

   3. SaveToStream 和 SaveToFile 方法

   SaveToStream 方法是将 MemoryStream 对象中的内容写入 Stream 所指定的流。其实现如下:

 

         procedure TCustomMemoryStream.SaveToStream(Stream: TStream);

         begin

           if FSize <> 0 then Stream.WriteBuffer(FMemory^, FSize);

         end;

 

   SaveToStream 方法调用了 Stream 的 WriteBuffer 方法,直接将 FMemory 中的内容按 FSize 字节长度写入流中。

   SaveToFile 方法是与 SaveToStream 方法相关的。 SaveToFile 方法首先创建了一个 FileStream 对象,然后把该文件 Stream 对象作为 SaveToStream 的参数,由 SaveToStream 方法执行写操作,其实现如下:

 

         procedure TCustomMemoryStream.SaveToFile(const FileName: string);

         var

           Stream: TStream;

         begin

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

           try

             SaveToStream(Stream);

           finally

             Stream.Free;

           end;

         end;

 

  在 Delphi 的许多对象的 SaveToStream 和 SaveToFile 、 LoadFromStream 和 LoadFromFile 方法的实现都有类似的嵌套结构。

 

TMemoryStream 对象

 

    

TMemoryStream 对象是一个管理动态内存中的数据的 Stream 对象,它是从 TCustomMemoryStream 中继承下来的,除了从 TCustomMemoryStream 中继承的属性和方法外,它还增加和覆盖了一些用于从磁盘文件和其它注台读数据的方法。它还提供了写入、消除内存内容的动态内存管理方法。下面

介绍它的这些属性和方法。

 

TMemoryStream 的属性和方法

 

   1. Capacity 属性

  声明: property Copacity: Longint; 

     Capacity 属性决定了分配给内存流的内存池的大小。这与 Size 属性有些不同。 Size 属性是描述流中数据的大小。在程序中可以将 Capacity 的值设置的比数据所需最大内存大一些,这样可以避免频繁地重新分配。

   2. Realloc 方法

  声明: function Realloc(var NewCapacity: Longint): Pointer; virtual; 

     Realloc 方法,以 8K 为单位分配动态内存,内存的大小由 NewCapacity 指定,函数返回指向所分配内存的指针。

   3. SetSize 方法

   SetSize 方法消除内存流中包含的数据,并将内存流中内存池的大小设为 Size 字节。如果 Size 为零,是 SetSize 方法将释放已有的内存池,并将 Memory 属性置为 nil ;否则, SetSize 方法将内存池大小调整为 Size 。

     4. Clear 方法

  声明: procedure Clear; 

     Clear 方法释放内存中的内存池,并将 Memory 属性置为 nil 。在调用 Clear 方法后, Size 和 Position 属性都为 0 。

   5. LoadFromStream 方法

  声明: procedure LoadFromStream(Stream: TStream); 

     LoadFromStream 方法将 Stream 指定的流中的全部内容复制到 MemoryStream 中,复制过程将取代已有内容,使 MemoryStream 成为 Stream 的一份拷贝。

   6. LoadFromFile 方法

  声明: procedure LoadFromFile(count FileName: String); 

     LoadFromFile 方法将 FileName 指定文件的所有内容复制到 MemoryStream 中,并取代已有内容。调用 LoadFromFile 方法后, MemoryStream 将成为文件内容在内存中的完整拷贝。

 

TMemoryStream 对象的实现原理

 

   TMemoryStream 从 TCustomMemoryStream 对象直接继承,因此可以享用 TCustomMemoryStream 的属性和方法。前面讲过, TCustomMemoryStream 是用于内存中数据操作的抽象对象,它为 MemoryStream 对象的实现提供了框架,框架中的内容还要由具体 MemoryStream 对象去填充。 TMemoryStrea

m 对象就是按动态内存管理的需要填充框架中的具体内容。下面介绍 TMemoryStream 对象的实 ? FBuffer := AllocMem(FDataSet.RecordSize);

               FRecord := FBuffer;

               if not FDataSet.GetCurrentRecord(FBuffer) then Exit;

               OpenMode := dbiReadOnly;

         end else

             begin

               if not (FDataSet.State in [dsEdit, dsInsert]) then DBError(SNotEditing);

               OpenMode := dbiReadWrite;

             end;

             Check(DbiOpenBlob(FDataSet.Handle, FRecord, FFieldNo, OpenMode));

           end;

           FOpened := True;

           if Mode = bmWrite then Truncate;

         end;

 

    该方法首先是用传入的 Field 参数给 FField , FDataSet , FRecord 和 FFieldNo 赋值。方法中用 AllocMem 按当前记录大小分配内存,并将指针赋给 FBuffer ,用 DataSet 部件的 GetCurrentRecord 方法,将记录的值赋给 FBuffer ,但不包括 BLOB 数据。

  方法中用到的 DbiOpenBlob 函数是 BDE 的 API 函数,该函数用于打开数据库中的 BLOB 字段。

  最后如果方法传入的 Mode 参数值为 bmWrite ,就调用 Truncate 将当前位置指针以后的

数据删除。

  分析这段源程序不难知道:

  ● 读写 BLOB 字段,不允许 BLOB 字段所在 DataSet 部件有 Filter ,否则产生异常事件

  ● 要读写 BLOB 字段,必须将 DataSet 设为编辑或插入状态

  ● 如果 BLOB 字段中的数据作了修改,则在创建 BLOB 流时,不再重新调用 DBiOpenBlob 函数,而只是简单地将 FOpened 置为 True ,这样可以用多个 BLOB 流对同一个 BLOB 字段读写

 

   Destroy 方法释放 BLOB 字段和为 FBuffer 分配的缓冲区,其实现如下:

 

         destructor TBlobStream.Destroy;

         begin

           if FOpened then

           begin

             if FModified then FField.FModified := True;

             if not FField.FModified then

               DbiFreeBlob(FDataSet.Handle, FRecord, FFieldNo);

           end;

           if FBuffer <> nil then FreeMem(FBuffer, FDataSet.RecordSize);

           if FModified then

           try

             FField.DataChanged;

           except

             Application.HandleException(Self);

           end;

         end;

 

  如果 BLOB 流中的数据作了修改,就将 FField 的 FModified 置为 True ;如果 FField 的 Modified 为 False 就释放 BLOB 字段,如果 FBuffer 不为空,则释放临时内存。最后根据 FModified 的值来决定是否启动 FField 的事件处理过程 DataChanged 。

  不难看出,如果 BLOB 字段作了修改就不释放 BLOB 字段,并且对 BLOB 字段的修改只有到 Destroy 时才提交,这是因为读写 BLOB 字段时都避开了 FField ,而直接调用 BDE API 函数。这一点是在应用 BDE API 编程中很重要,即一定要修改相应数据库部件的状态。

   2. Read 和 Write 方法的实现

   Read 和 Write 方法都调用 BDE API 函数完成数据库 BLOB 字段的读写,其实现如下:

  

         function TBlobStream.Read(var Buffer; Count: Longint): Longint;

         var

            Status: DBIResult;

         begin

           Result := 0;

           if FOpened then

           begin

             Status := DbiGetBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition,

                                                             Count, @Buffer, Result);

             case Status of

               DBIERR_NONE, DBIERR_ENDOFBLOB:

                 begin

                   if FField.FTransliterate then

                     NativeToAnsiBuf(FDataSet.Locale, @Buffer, @Buffer, Result);

                   Inc(FPosition, Result);

                 end;

               DBIERR_INVALIDBLOBOFFSET:

                 {Nothing};

             else

               DbiError(Status);

             end;

           end;

         end;

 

   Read 方法使用了 BDE 

API 的 DbiGetBlob 函数从 FDataSet 中读取数据,在本函数中,各参数的含义是这样的: FDataSet.Handle 代表 DataSet 的 BDE 句柄, FReacord 表示 BLOB 字段所在记录, FFieldNo 表示 BLOB 字段号, FPosition 表示要读的的数据的起始位置, Count 表示要读的字节数, Buffer 是读出数据所占的内存,

Result 是实际读出的字节数。该 BDE 函数返回函数调用的错误状态信息。

   Read 方法还调用了 NativeToAnsiBuf 进行字符集的转换。

 

         function TBlobStream.Write(const Buffer; Count: Longint): Longint;

         var

           Temp: Pointer;

         begin

           Result := 0;

           if FOpened then

           begin

             if FField.FTransliterate then

              begin

               GetMem(Temp, Count);

               try

                 AnsiToNativeBuf(FDataSet.Locale, @Buffer, Temp, Count);

                 Check(DbiPutBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition,

                   Count, Temp));

               finally

                 FreeMem(Temp, Count);

               end;

             end else

               Check(DbiPutBlob(FDataSet.Handle, FRecord, FFieldNo, FPosition,

                                                       Count, @Buffer));

             Inc(FPosition, Count);

             Result := Count;

             FModified := True;

           end;

         end;

 

     Write 方法调用了 BDE API 的 DbiPutBlob 函数实现往数据库 BLOB 字段存储数据。

     该函数的各参数含义如下:

 

                  调用函数 DbiPutBlob 的各传入参数的含义

    ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

       参数名           含义

     ──────────────────────────────

        FDataSetHandle            写入的数据库的 BDE 句柄

       FRecord                   写入数据的 BLOB 字段所在的记录

        FFieldNo                  BLOB 字段号

         FPosition                  写入的起始位置

        Count                     写入的数据的字节数

         Buffer                     所写入的数据占有的内存地址

     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

标志,该标志意味着后面存储有一连串的项目。 Reader 对象,在读这一连串项目时先调用 ReadListBegin 方法读取该标志位,然后用 EndOfList 判断是否列表结束,并用循环语句读取项目。在调用 WriteListBegin 方法的后面必须调用 WriteListEnd 方法写列表结束标志,相应的在 Reader 对象中

有 ReadListEnd 方法读取该结束标志。

   5. WriteListEnd 方法

  声明: procedure WriteListEnd; 

     WriteListEnd 方法在流中,写入项目列表结束标志,它是与 WriteListBegin 相匹配的方法。

   6. WriteBoolean 方法

  声明: procedure WriteBoolean(Value: Boolean); 

     WriteBoolean 方法将 Value 传入的布尔值写入流中。

   7. WriteChar 方法

  声明: procedure WriteChar(Value: char); 

     WriteChar 方法将 Value 中的字符写入流中。

   8. WriteFloat 方法

  声明: procedure WriteFloat(Value: Extended); 

     WriteFloat 方法将 Value 传入的浮点数写入流中。

   9. WriteInteger 方法

  声明: procedure WriteInteger(Value: Longint); 

     WriteInteger 方法将 Value 中的整数写入流中。

   10. WriteString 方法

  声明: procedure WriteString(const Value: string); 

     WriteString 方法将 Value 中的字符串写入流中。

   11. WriteIdent 方法

  声明: procedure WriteIdent(const Ident: string); 

     WriteIdent 方法将 Ident 传入的标识符写入流中。

   12. WriteSignature 方法

  声明: procedure WriteSignature; 

     WriteSignature 方法将 Delphi Filer 对象标签写入流中。 WriteRootComponent 方法在将部件写入流之前先调用 WriteSignature 方法写入 Filer 标签。 Reader 对象在读部件之前调用 ReadSignature 方法读取该标签以指导读操作。

   13. WritComponent 方法

  声明: procedure WriteComponent(Component: TComponent); 

     WriteComponent 方法调用参数 Component 的 WriteState 方法将部件写入流中。在调用 WriteState 之前, WriteComponent 还将 Component 的 ComponetnState 属性置为 csWriting 。当 WriteState 返回时再清除 csWriting.

     14. WriteRootComponent 方法

  声明: procedure WriteRootComponent(Root: TComponent); 

     WriteRootComponent 方法将 Writer 对象 Root 属性设为参数 Root 带的值,然后调用 WriteSignature 方法往流中写入 Filer 对象标签,最后调用 WriteComponent 方法在流中存储 Root 部件。

相关文章:

  • 2022-12-23
  • 2022-01-19
  • 2021-10-11
  • 2021-11-08
  • 2022-12-23
  • 2021-07-28
  • 2021-08-30
猜你喜欢
  • 2022-12-23
  • 2021-10-22
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案