全國(guó)計(jì)算機(jī)等級(jí)考試二級(jí)Delphi輔導(dǎo)講義 216

字號(hào):

3. FlushBuffer的實(shí)現(xiàn)
    FlushBuffer方法用于清除Reader對(duì)象的內(nèi)部緩沖區(qū)中的內(nèi)容,保持Reader對(duì)象和流在位置(Position)上的同步,其實(shí)現(xiàn)如下:
    procedure TReader.FlushBuffer;
    begin
    FStream.Position := FStream.Position - (FBufEnd - FBufPos);
    FBufPos := 0;
    FBufEnd := 0;
    end;
    4. ReadListBegin、ReadListEnd和EndOfList方法
    這三個(gè)方法都是用于從Reader對(duì)象的流中讀取一連串的項(xiàng)目,并且這些項(xiàng)目都由WriteListBegin寫(xiě)入的標(biāo)志標(biāo)定開(kāi)始和WriteListEnd寫(xiě)入標(biāo)志,標(biāo)定結(jié)束,在讀循環(huán)中用EndOfList進(jìn)行判斷。它們是在Reader對(duì)象讀取流中數(shù)據(jù)時(shí)經(jīng)常用于的。它們的實(shí)現(xiàn)如下:
    procedure TReader.ReadListBegin;
    begin
    CheckValue(vaList);
    end;
    procedure TReader.ReadListEnd;
    begin
    CheckValue(vaNull);
    end;
    function TReader.EndOfList: Boolean;
    begin
    Result := ReadValue = vaNull;
    Dec(FBufPos);
    end;
    項(xiàng)目表開(kāi)始標(biāo)志是VaList,項(xiàng)目表結(jié)束標(biāo)志是VaNull,VaList和VaNull都是枚舉類型TValueType定義的常量。
    它們實(shí)現(xiàn)中調(diào)用的CheckValue是TReader的私有方法,其實(shí)現(xiàn)如下:
    procedure TReader.CheckValue(Value: TValueType);
    begin
    if ReadValue <> Value then
    begin
    Dec(FBufPos);
    SkipValue;
    PropValueError;
    end;
    end;
    CheckValue方法的功能是檢測(cè)緊接著要讀的值是否是Value指定的類型。如果不是則跳過(guò)該項(xiàng)目并觸發(fā)一個(gè)SInvalidPropertyValue錯(cuò)誤。
    EndOfList函數(shù)只是簡(jiǎn)單地判斷下一字節(jié)是否是VaNull將判斷結(jié)果返回,并將字節(jié)移回原來(lái)位置。
    5. 簡(jiǎn)單數(shù)據(jù)類型讀方法的實(shí)現(xiàn)
    簡(jiǎn)單數(shù)據(jù)類型指的是布爾型、字符型、整型、字符串型、浮點(diǎn)型、集合類型和標(biāo)識(shí)符。將它們放在一起介紹是因?yàn)樗鼈兊膶?shí)現(xiàn)方法類似。
    因?yàn)樗鼈兊膶?shí)現(xiàn)都用到了ReadValue方法,因此先來(lái)介紹ReadValue方法的實(shí)現(xiàn):
    function TReader.ReadValue: TValueType;
    begin
    Read(Result, SizeOf(Result));
    end;
    該方法調(diào)用私有方法Read,從Reader對(duì)象流中讀一個(gè)字節(jié),并移動(dòng)位置指針。
    ReadValue方法專門(mén)從流中讀取值的類型的,所有的數(shù)據(jù)讀寫(xiě)方法中在讀取數(shù)據(jù)前都要調(diào)用ReadValue方法判斷是否是所要讀的數(shù)據(jù)。如果是,則調(diào)用Read方法讀取數(shù)據(jù);否則觸發(fā)一個(gè)異常事件,下面看Integer類型的讀方法:
    function TReader.ReadInteger: Longint;
    var
    S: Shortint;
    I: Smallint;
    begin
    case ReadValue of
    vaInt8:
    begin
    Read(S, SizeOf(Shortint));
    Result := S;
    end;
    vaInt16:
    begin
    Read(I, SizeOf(I));
    Result := I;
    end;
    vaInt32:
    Read(Result, SizeOf(Result));
    else
    PropValueError;
    end;
    end;
    因?yàn)镈elphi 2.0中,整型可分8位、16位和32位,因此讀取整型數(shù)據(jù)時(shí)分別作了判斷。
    布爾類型的數(shù)據(jù)是直接放在值類型標(biāo)志上,如果類型為VaTrue,則值為T(mén)rue;如果類型為VaFalse,則值為False。
    function TReader.ReadBoolean: Boolean;
    begin
    Result := ReadValue = vaTrue;
    end;
    ReadString方法也利用ReadValue方法判斷是字符串還是長(zhǎng)字符串。
    function TReader.ReadString: string;
    var
    L: Integer;
    begin
    L := 0;
    case ReadValue of
    vaString:
    Read(L, SizeOf(Byte));
    vaLString:
    Read(L, SizeOf(Integer));
    else
    PropValueError;
    end;
    SetString(Result, PChar(nil), L);
    Read(Pointer(Result)^, L);
    end;
    如果VaString類型緊接著一個(gè)字節(jié)存有字符串的長(zhǎng)度;如果是VaLString類,則緊接著兩個(gè)字節(jié)存放字符串長(zhǎng)度,然后根據(jù)字符串長(zhǎng)度用SetString過(guò)程給分配空間,用Read方法讀出數(shù)據(jù)。
    ReadFloat方法允許將整型值轉(zhuǎn)換為浮點(diǎn)型。
    function TReader.ReadFloat: Extended;
    begin
    if ReadValue = vaExtended then Read(Result, SizeOf(Result)) else
    begin
    Dec(FBufPos);
    Result := ReadInteger;
    end;
    end;
    字符類型數(shù)據(jù)設(shè)有直接的標(biāo)志,它是根據(jù)VaString后面放一個(gè)序值為1的字節(jié)來(lái)判斷的。
    function TReader.ReadChar: Char;
    begin
    CheckValue(vaString);
    Read(Result, 1);
    if Ord(Result) <> 1 then
    begin
    Dec(FBufPos);
    ReadStr;
    PropValueError;
    end;
    Read(Result, 1);
    end;
    出于讀取DFM文件需要,F(xiàn)iler對(duì)象支持讀取標(biāo)識(shí)符。
    function TReader.ReadIdent: string;
    var
    L: Byte;
    begin
    case ReadValue of
    vaIdent:
    begin
    Read(L, SizeOf(Byte));
    SetString(Result, PChar(nil), L);
    Read(Result[1], L);
    end;
    vaFalse:
    Result := 'False';
    vaTrue:
    Result := 'True';
    vaNil:
    Result := 'nil';
    else
    PropValueError;
    end;
    end;
    一般說(shuō)來(lái),各種復(fù)雜的數(shù)據(jù)結(jié)構(gòu)都是由這些簡(jiǎn)單數(shù)據(jù)組成;定義了這些方法等于給讀各種類型的數(shù)據(jù)提供了元操作,使用很方便。例如,讀取字符串類型的數(shù)據(jù)時(shí),如果采用傳流方法還要判斷字符串的長(zhǎng)度,使用ReadString方法就不同了。但應(yīng)該特別注意的是這些類型數(shù)據(jù)的存儲(chǔ)格式是由Delphi設(shè)計(jì)的與簡(jiǎn)單數(shù)據(jù)類型有明顯的不同。因此,存入數(shù)據(jù)時(shí)應(yīng)當(dāng)使用Writer對(duì)象相應(yīng)的方法,而且在讀數(shù)據(jù)前要用NextValue方法進(jìn)行判斷,否則會(huì)觸發(fā)異常事件。