20.2.3 TReader對象
TReader對象是可實例化的用于從相聯系的流中讀取數據的Filer對象。TReader對象從TFiler繼承下來,除了從TFiler繼承的屬性和方法外,TReader聲明了不少屬性、方法和事件。
Owner和Parent屬性用于表示從Reader對象的流中讀取的部件的擁有者和雙親結點。onError,OnFindMethod和OnSetName事件使應用程序在運行中讀數據時能定制響應方式。除了覆蓋了一些從TFiler對象中繼承的方法外,TReader對象還定義大量的讀不同類型的數據和觸發事件的方法。
20.2.3.1 TReader對象的屬性和方法
1. Owner屬性
聲明:property Owner: TComponent;
Reader對象的Owner屬性存儲了將用來給從Reader的流中讀出的部件的Owner屬性賦值的部件。
2. Parent屬性
聲明:property Parent: TComponent;
Parent屬性存儲將用來給從Reader的流中讀出所有控制的Parent屬性賦值的部件。
3. Position屬性
聲明:propertion: Longint;
Reader對象的Position屬性表示相聯的流中讀的當前位置。Position的值還應包括讀緩沖區的大小。對于Reader 對象,Position的值大于流的Position 的值。如果將Position的值設得超過當前緩沖區,將引起調用FlushBuffer。
4. BeginReferences方法
聲明:procedure BeginReferences;
BeginReferences方法啟動一連串關于讀部件的命令,這些部件包含相互間的交叉引用。在使用上通常和FixupReferences和EndReferences一起放在Try…finally程序塊中。
在調用了BeginReferences后,Reader對象創建讀取所有對象和名字的列表。所有的獨立對象被讀出后,調用FixupReferences方法將名字的相互從流中轉移到對象實例中。最后調用EndReferences方法釋放列表。
處理部件相互引用的程序塊形式如下:
BeginReferences; { 創建臨時列表 }
try
{ 讀出所有部件并將它們的名字放在一臨時列表中 }
…
FixupReferences; { 分 解 }
finally
EndReferences; { 釋放臨時列表 }
end;
5. FixUpReferences方法
聲明:procedure FixupReferences;
FixupReferences方法分解從流中讀出的存在各種相互依賴部件的引用關系。FixupReferences總在try…finally塊中并配合BeginReferences和EndReferences一起使用。
6. EndReferences方法
聲明:procedure EndReferences;
EndReferences方法終止處理相互引用的塊操作,釋放對象列表。它總配合BeginReferences和FixupReferences一起使用。
7. ReadListBegin方法
聲明:procedure ReadListBegin;
ReadListBegin方法從Reader對象相聯的流中讀取列表開始標志。如果流中緊接著要讀取的項目不是一個由WritelistBegin方法寫入的列表起始標志,ReadListBegin將引起一個讀異常事件。
通常在調用ReadlistBegin方法之后,緊跟著一個讀項目的循環,循環以EndfList方法返回True 終止條件。這時,預示流中的下一個項目是列表結束標志,需要調用ReadListEnd方法。
8. ReadListEnd方法
聲明:procedure ReadListEnd;
ReadListEnd 方法從流中讀取列表結束標志。如果所讀的項目不是一個列表結束標志,ReadListEnd方法引發一個EReadError異常事件。
9. EndOfList方法
聲明:function EndOfList: Boolean;
如果Reader對象讀到項目列表結果標志,EndOfList方法返回True。
TStrings對象在從Reader對象讀取項目列表時使用了ReadListBegin和ReadListEnd方法。下面的ReadData是TStrings的方法,用于在DefineProperties方面中讀string數據。
procedure TStrings.ReadData(Reader: TReader);
begin
Reader.ReadListBegin; { 讀列表開始標志 }
Clear; { 清除已有的字符串 }
while not Reader.EndOfList do { 只要還有數據 … }
Add(Reader.ReadString); { …讀一個字符串并將其加在列表中 }
Reader.ReadListEnd; { 越過列表結束標志 }
end;
10. ReadSignature方法
聲明:procedure ReadSignature;
ReadSignature方法從流中讀取部件之前首先調用ReadSignature方法。在載入對象之前檢測標簽。Reader對象就能防止疏忽大意,導致讀取無效或過時的數據。Filer標簽是四個字符,對于Delphi 2.0,該標簽是“TPF0”。
11. ReadPrefix方法
聲明:procedure ReadPrefix(var Plags: TFilerFlags; var AChild, Pos: Integer);
ReadPrefix方法的功能與ReadSignature的很相象,只不過它是讀取流中部件前面的標志(PreFix)。當一個Write對象將部件寫入流中時,它在部件前面預寫了兩個值,第一個值是指明部件是否是從祖先窗體中繼承的窗體和它在窗體中的位置是否重要的標志;第二個值指明它在祖先窗體創建次序。ReadComponent方法自動調用ReadPrefix。但如果需要獨立讀取部件的預讀標志,也可直接調用該方向。
12. OnFindMethod事件
聲明:property OnFindMethod: TFindMethodEvent;
OnFindMethod事件,發生在Reader對象讀取對象的方法指針時,屬性為方法指針的通常都是事件。
響應OnFindMethod事件的理由,通常是處理過程找不到方法的情況。在FindMethod方法沒有找到由Name指定的方法的情況下,如果它將OnFindMethod方法的Error 參數設為True,將引起ReadError異常事件;反之,將Error參數置為False,將防止FindMethod方法引發異常事件。
13. Error方法
聲明:function Error(const Message: String): Boolean; virtual;
Error方法定義在Reader對象的protected部分,它是用于Reader對象的onError事件。其返回值決定是否繼續錯誤處理過程。如果返回值為True,則表示用程序應當繼續錯誤處理;如果返回值為False,則表示錯誤情況被忽略。
如果讀部件或屬性出錯。Reader對象調用Error方法。缺省情況下,Error將返回值設為False,然后調用onError事件處理過程。
TReader對象總是在try…except程序塊的except部分,并提供用戶忽略錯誤的機會。Error的使用方法如下:
try
… { 讀部件 }
except
on E: Exception do
begin
…{ 執行一些清除操作 }
if Error(E.Message) then raise;
end;
end;
14. onError事件
聲明:property onError: TReaderError;
當Reader對象讀取數據出錯時將引發onError事件。通過處理onError事件,可以有選擇地處理或忽略錯誤。
傳給onError事件處理過程的最后一個參數是名為Handled的var參數。在缺省情況下,Error方法將Handled置為True。這將阻止錯誤更進一步處理。如果事件處理過程仍舊將Handled置為False,Reader對象將引發一個EReadError異常事件。
15. SetName方法
聲明:procedure SetName(Component: TComponent; var Name: String virtual);
SetName方法允許Reader對象在將從流中讀取的部件的Name值賦給部件的Name屬性前修改Name值。ReadComponent方法在讀取部件的屬性值和其它數據前先讀部件的類型和名字在讀完名字后,ReadComponent將所讀的名字作為Name參數傳給SetName,Name 是個var參數,因此SetName能在返回前修改字符串值。SetName還調用了OnSetName事件處理過程,將名字字符串作為var參數傳入事件處理過程中,因此,事件處理過程也可修改字符串的值。
16. OnSetName事件
聲明:property OnSetName: TSetNameEvent;
OnSetName事件發生在Read對象設置部件的Name屬性前,OnSetName事件處理過程的var參數Name參數是一個var參數,因此,事件處理過程再將Name賦給部件前,可以修改Name的值。這對于想過濾窗體中部件的名字是很有幫助的。
下面的OnSetName事件處理過程,命名了名字中包含“Button”的部件,并用“PushButton”替代。
procedure TForm1.ReaderSetName(Reader: TReader; Component: TComponent;
var Name: string);
var
ButtonPos: Integer;
begin
ButtonPos := Pos('Button', Name);
if ButtonPos <> 0 then
Name := Copy(Name, 1, ButtonPos - 1) + 'PushButton' +
Copy(Name, ButtonPos + 6, Length(Name));
end; [1] [2] 下一頁
|