Delphi Stream 介紹

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部件。

發佈了31 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章