12. WriteSignature方法
聲明:procedure WriteSignature;
WriteSignature方法將Delphi Filer對象標(biāo)簽寫入流中。WriteRootComponent方法在將部件寫入流之前先調(diào)用WriteSignature方法寫入Filer標(biāo)簽。Reader對象在讀部件之前調(diào)用ReadSignature方法讀取該標(biāo)簽以指導(dǎo)讀操作。
13. WritComponent方法
聲明:procedure WriteComponent(Component: TComponent);
WriteComponent方法調(diào)用參數(shù)Component的WriteState方法將部件寫入流中。在調(diào)用WriteState之前,WriteComponent還將Component的ComponetnState屬性置為csWriting。當(dāng)WriteState返回時再清除csWriting.
14. WriteRootComponent方法
聲明:procedure WriteRootComponent(Root: TComponent);
WriteRootComponent方法將Writer對象Root屬性設(shè)為參數(shù)Root帶的值,然后調(diào)用WriteSignature方法往流中寫入Filer對象標(biāo)簽,最后調(diào)用WriteComponent方法在流中存儲Root部件。
20.2.2.2 TWriter對象的實現(xiàn)
TWriter對象提供了許多往流中寫各種類型數(shù)據(jù)的方法,這對于程序員來說是很重要的功能。TWrite對象往流中寫數(shù)據(jù)是依據(jù)不同的數(shù)據(jù)采取不同的格式的。 因此要掌握TWriter對象的實現(xiàn)和應(yīng)用方法,必須了解Writer對象存儲數(shù)據(jù)的格式。
首先要說明的是,每個Filer對象的流中都包含有Filer對象標(biāo)簽。該標(biāo)簽占四個字節(jié)其值為“TPF0”。Filer對象為WriteSignature和ReadSignature方法存取該標(biāo)簽。該標(biāo)簽主要用于Reader對象讀數(shù)據(jù)(部件等)時,指導(dǎo)讀操作。
其次,Writer對象在存儲數(shù)據(jù)前都要留一個字節(jié)的標(biāo)志位,以指出后面存放的是什么類型的數(shù)據(jù)。該字節(jié)為TValueType類型的值。TValueType是枚舉類型,占一個字節(jié)空間,其定義如下:
TValueType = (VaNull, VaList, VaInt8, VaInt16, VaInt32, VaEntended, VaString, VaIdent,
VaFalse, VaTrue, VaBinary, VaSet, VaLString, VaNil, VaCollection);
因此,對Writer對象的每一個寫數(shù)據(jù)方法,在實現(xiàn)上,都要先寫標(biāo)志位再寫相應(yīng)的數(shù)據(jù);而Reader對象的每一個讀數(shù)據(jù)方法都要先讀標(biāo)志位進行判斷,如果符合就讀數(shù)據(jù),否則產(chǎn)生一個讀數(shù)據(jù)無效的異常事件。VaList標(biāo)志有著特殊的用途,它是用來標(biāo)識后面將有一連串類型相同的項目,而標(biāo)識連續(xù)項目結(jié)束的標(biāo)志是VaNull。因此,在Writer對象寫連續(xù)若干個相同項目時,先用WriteListBegin寫入VaList標(biāo)志,寫完數(shù)據(jù)項目后,再寫出VaNull標(biāo)志;而讀這些數(shù)據(jù)時,以ReadListBegin開始,ReadListEnd結(jié)束,中間用EndofList函數(shù)判斷是否有VaNull標(biāo)志。
下面就介紹它們的實現(xiàn)。
1. TWriter對象屬性的實現(xiàn)
TWriter對象直接從TFiler對象繼承,它只增加了Position和RootAncestor屬性。
RootAncestor屬性在private部分有數(shù)據(jù)域FRootAncestor存入其值。在屬性定義的讀與控制上都是直接讀取該值。
Position屬性的定義中包含了兩個讀寫控制方法:GetPosition和SetPosition:
TWriter = class(TFiler)
private
FRootAncestor: TComponent;
…
function GetPosition: Longint;
procedure SetPosition(Value: Longint);
public
…
property Position: Longint read GetPosition write SetPosition;
property RootAncestor: TComponent read FRootAncestor write FRootAncestor;
end;
GetPosition和SetPosition方法實現(xiàn)如下:
function TWriter.GetPosition: Longint;
begin
Result := FStream.Position + FBufPos;
end;
procedure TWriter.SetPosition(Value: Longint);
var
StreamPosition: Longint;
begin
StreamPosition := FStream.Position;
{ 只清除越界的緩沖區(qū) }
if (Value < StreamPosition) or (Value > StreamPosition + FBufPos) then
begin
WriteBuffer;
FStream.Position := Value;
end
else FBufPos := Value - StreamPosition;
end;
WriteBuffer是TWriter對象定義的私有方法,它的作用是將Writer 對象內(nèi)部緩沖區(qū)中的有效數(shù)據(jù)寫入流中,并將FBufPos置為0。Writer對象的FlushBuffer對象就是用WriteBuffer方法刷新緩沖區(qū)。
在SetPosition方法中,如果Value值超出了邊界(FStream.Position,F(xiàn)Stream.Position + FBufPos),就將緩沖區(qū)中的內(nèi)容寫入流,重新設(shè)置緩沖區(qū)在流中的相對位置;否則,就只是移動FBufPos指針。
2. TWriter方法的實現(xiàn)
、 WriteListBegin和WriteListEnd的實現(xiàn)
這兩個方法都是用于寫連續(xù)若干個相同類型的值。WriteListBegin寫入VaList標(biāo)志,WriteListEnd寫入VaNull標(biāo)志。
procedure TWriter.WriteListBegin;
begin
WriteValue(vaList);
end;
procedure TWriter.WriteListEnd;
begin
WriteValue(vaNull);
end;
這兩個方法都調(diào)用TWriter對象的WriteValue方法,該方法主要用于寫入TValueType類型的值。
procedure TWriter.WriteValue(Value: TValueType);
begin
Write(Value, SizeOf(Value));
end;
、 簡單數(shù)據(jù)類型的寫入
簡單數(shù)據(jù)類型指的是整型、字符型、字符串型、浮點型、布爾型等。TWriter對象都定義了相應(yīng)的寫入方法。
WriteInteger方法用于寫入整型數(shù)據(jù)。
procedure TWriter.WriteInteger(Value: Longint);
begin
if (Value >= -128) and (Value <= 127) then
begin
WriteValue(vaInt8);
Write(Value, SizeOf(Shortint));
end else
if (Value >= -32768) and (Value <= 32767) then
begin
WriteValue(vaInt16);
Write(Value, SizeOf(Smallint));
end else
begin
WriteValue(vaInt32);
Write(Value, SizeOf(Longint));
end;
end;
WriteInteger方法將整型數(shù)據(jù)分為8位、16位和32位三種,并分別用vaInt8、vaInt16和VaInt32。
WriteBoolean用于寫入布爾型數(shù)據(jù):
procedure TWriter.WriteBoolean(Value: Boolean);
begin
if Value then
WriteValue(vaTrue) else
WriteValue(vaFalse);
end;
與其它數(shù)據(jù)類型不同的是布爾型數(shù)據(jù)只使用了標(biāo)志位是存儲布爾值,在標(biāo)志位后沒有數(shù)據(jù)。
WriteFloat方法用于寫入浮點型數(shù)據(jù)。
procedure TWriter.WriteFloat(Value: Extended);
begin
WriteValue(vaExtended);
Write(Value, SizeOf(Extended));
end;
字符串“True”、“False”和“nil”作為標(biāo)識符傳入是由于Delphi的特殊需要。如果是“True”、“False”和“nil”則寫入VaTrue、VaFalse和VaNil,否則寫入VaIdent標(biāo)志,接著以字符串形式寫入標(biāo)識符。
WriteString方法用于寫入字符串
procedure TWriter.WriteString(const Value: string);
var
L: Integer;
begin
L := Length(Value);
if L <= 255 then
begin
WriteValue(vaString);
Write(L, SizeOf(Byte));
end else
begin
WriteValue(vaLString);
Write(L, SizeOf(Integer));
end;
Write(Pointer(Value)^, L);
end;
Delphi的字符串類型有兩種。一種長度小于256個字節(jié),另一種長度小于65536 個字節(jié)。WriteString方法區(qū)分這兩類情況存儲字符串,一種設(shè)置VaStirng標(biāo)志,另一種設(shè)置VaLString。然后存儲字符串的長度值,最后存儲字符串?dāng)?shù)據(jù)。
WriteChar方法用于寫入字符。
procedure TWriter.WriteChar(Value: Char);
begin
WriteString(Value);
end;
字符類型的讀寫是用讀寫字符串的方法,在讀的時候,判斷字節(jié)數(shù)為1時,則為字符型。
、 部件的寫入
TWriter對象中與寫入部件有關(guān)的方法有WriteSignature、WritePrefix、WriteComponent、WriteDescendant和WriteRootComponent。
WriteSignature方法用于往流中寫入Filer對象標(biāo)簽。
procedure TWriter.WriteSignature;
begin
Write(FilerSignature, SizeOf(FilerSignature));
end;
FilerStgnature是字符串常量,其值為“TPF0”,代表對象標(biāo)簽。
WritePrefix方法用于在寫入部件前寫入ffInherited和ffChildPos標(biāo)志,這些標(biāo)志表示部件的繼承特征和創(chuàng)建序值特征。
procedure TWriter.WritePrefix(Flags: TFilerFlags; AChildPos: Integer);
var
Prefix: Byte;
begin
if Flags <> [] then
begin
Prefix := $F0 or Byte(Flags);
Write(Prefix, SizeOf(Prefix));
if ffChildPos in Flags then WriteInteger(AChildPos);
end;
end;
如果ffChildPos置位,則存入部件在Owner中的創(chuàng)建序值。更詳細的信息請參閱TReader的ReadPrefix方法。
WriteComponent方法往流中寫入部件。
procedure TWriter.WriteComponent(Component: TComponent);
function FindAncestor(const Name: string): TComponent;
begin
…
end;
begin
Include(Component.FComponentState, csWriting);
if Assigned(FAncestorList) then
Ancestor := FindAncestor(Component.Name);
Component.WriteState(Self);
Exclude(Component.FComponentState, csWriting);
end;
方法中用Component的WritState方法寫入部件的屬性。在寫入之前將Component.FComponentState置為csWriting寫入完后再將csWriting復(fù)位。
WriteDescendant是根據(jù)祖先AAncestor的情況寫入部件Root。
procedure TWriter.WriteDescendent(Root: TComponent; AAncestor: TComponent);
begin
FRootAncestor := AAncestor;
FAncestor := AAncestor;
FRoot := Root;
WriteSignature;
WriteComponent(Root);
end;
方法先調(diào)用WriteSignature方法寫入Filer對象標(biāo)簽。然后調(diào)用WriteComponent將部件Root寫入流。
WriteRootComponent方法則是調(diào)用WriteDescendant方法寫入部件,只是將后者的Ancestor參數(shù)以nil值傳入。
procedure TWriter.WriteRootComponent(Root: TComponent);
begin
WriteDescendent(Root, nil);
end;
20.2.3 TReader對象
TReader對象是可實例化的用于從相聯(lián)系的流中讀取數(shù)據(jù)的Filer對象。TReader對象從TFiler繼承下來,除了從TFiler繼承的屬性和方法外,TReader聲明了不少屬性、方法和事件。
Owner和Parent屬性用于表示從Reader對象的流中讀取的部件的擁有者和雙親結(jié)點。OnError,OnFindMethod和OnSetName事件使應(yīng)用程序在運行中讀數(shù)據(jù)時能定制響應(yīng)方式。除了覆蓋了一些從TFiler對象中繼承的方法外,TReader對象還定義大量的讀不同類型的數(shù)據(jù)和觸發(fā)事件的方法。
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屬性表示相聯(lián)的流中讀的當(dāng)前位置。Position的值還應(yīng)包括讀緩沖區(qū)的大小。對于Reader 對象,Position的值大于流的Position 的值。如果將Position的值設(shè)得超過當(dāng)前緩沖區(qū),將引起調(diào)用FlushBuffer。
4. BeginReferences方法
聲明:procedure BeginReferences;
BeginReferences方法啟動一連串關(guān)于讀部件的命令,這些部件包含相互間的交叉引用。在使用上通常和FixupReferences和EndReferences一起放在Try…finally程序塊中。
在調(diào)用了BeginReferences后,Reader對象創(chuàng)建讀取所有對象和名字的列表。所有的獨立對象被讀出后,調(diào)用FixupReferences方法將名字的相互從流中轉(zhuǎn)移到對象實例中。最后調(diào)用EndReferences方法釋放列表。
處理部件相互引用的程序塊形式如下:
BeginReferences; { 創(chuàng)建臨時列表 }
try
{ 讀出所有部件并將它們的名字放在一臨時列表中 }
…
FixupReferences; { 分 解 }
finally
EndReferences; { 釋放臨時列表 }
end;
5. FixUpReferences方法
聲明:procedure FixupReferences;
FixupReferences方法分解從流中讀出的存在各種相互依賴部件的引用關(guān)系。FixupReferences總在try…finally塊中并配合BeginReferences和EndReferences一起使用。
6. EndReferences方法
聲明:procedure EndReferences;
EndReferences方法終止處理相互引用的塊操作,釋放對象列表。它總配合BeginReferences和FixupReferences一起使用。
7. ReadListBegin方法
聲明:procedure ReadListBegin;
ReadListBegin方法從Reader對象相聯(lián)的流中讀取列表開始標(biāo)志。如果流中緊接著要讀取的項目不是一個由WritelistBegin方法寫入的列表起始標(biāo)志,ReadListBegin將引起一個讀異常事件。
通常在調(diào)用ReadlistBegin方法之后,緊跟著一個讀項目的循環(huán),循環(huán)以EndfList方法返回True 終止條件。這時,預(yù)示流中的下一個項目是列表結(jié)束標(biāo)志,需要調(diào)用ReadListEnd方法。
8. ReadListEnd方法
聲明:procedure ReadListEnd;
ReadListEnd 方法從流中讀取列表結(jié)束標(biāo)志。如果所讀的項目不是一個列表結(jié)束標(biāo)志,ReadListEnd方法引發(fā)一個EReadError異常事件。
9. EndOfList方法
聲明:function EndOfList: Boolean;
如果Reader對象讀到項目列表結(jié)果標(biāo)志,EndOfList方法返回True。
TStrings對象在從Reader對象讀取項目列表時使用了ReadListBegin和ReadListEnd方法。下面的ReadData是TStrings的方法,用于在DefineProperties方面中讀string數(shù)據(jù)。
procedure TStrings.ReadData(Reader: TReader);
begin
Reader.ReadListBegin; { 讀列表開始標(biāo)志 }
Clear; { 清除已有的字符串 }
while not Reader.EndOfList do { 只要還有數(shù)據(jù) … }
Add(Reader.ReadString); { …讀一個字符串并將其加在列表中 }
Reader.ReadListEnd; { 越過列表結(jié)束標(biāo)志 }
end;
10. ReadSignature方法
聲明:procedure ReadSignature;
ReadSignature方法從流中讀取部件之前首先調(diào)用ReadSignature方法。在載入對象之前檢測標(biāo)簽。Reader對象就能防止疏忽大意,導(dǎo)致讀取無效或過時的數(shù)據(jù)。Filer標(biāo)簽是四個字符,對于Delphi 2.0,該標(biāo)簽是“TPF0”。
11. ReadPrefix方法
聲明:procedure ReadPrefix(var Plags: TFilerFlags; var AChild, Pos: Integer);
ReadPrefix方法的功能與ReadSignature的很相象,只不過它是讀取流中部件前面的標(biāo)志(PreFix)。當(dāng)一個Write對象將部件寫入流中時,它在部件前面預(yù)寫了兩個值,第一個值是指明部件是否是從祖先窗體中繼承的窗體和它在窗體中的位置是否重要的標(biāo)志;第二個值指明它在祖先窗體創(chuàng)建次序。ReadComponent方法自動調(diào)用ReadPrefix。但如果需要獨立讀取部件的預(yù)讀標(biāo)志,也可直接調(diào)用該方向。
12. OnFindMethod事件
聲明:property OnFindMethod: TFindMethodEvent;
OnFindMethod事件,發(fā)生在Reader對象讀取對象的方法指針時,屬性為方法指針的通常都是事件。
響應(yīng)OnFindMethod事件的理由,通常是處理過程找不到方法的情況。在FindMethod方法沒有找到由Name指定的方法的情況下,如果它將OnFindMethod方法的Error 參數(shù)設(shè)為True,將引起ReadError異常事件;反之,將Error參數(shù)置為False,將防止FindMethod方法引發(fā)異常事件。
相關(guān)推薦:2010年9月計算機等級考試試題及答案解析專題北京 | 天津 | 上海 | 江蘇 | 山東 |
安徽 | 浙江 | 江西 | 福建 | 深圳 |
廣東 | 河北 | 湖南 | 廣西 | 河南 |
海南 | 湖北 | 四川 | 重慶 | 云南 |
貴州 | 西藏 | 新疆 | 陜西 | 山西 |
寧夏 | 甘肅 | 青海 | 遼寧 | 吉林 |
黑龍江 | 內(nèi)蒙古 |