5. 簡單數據類型讀方法的實現
簡單數據類型指的是布爾型、字符型、整型、字符串型、浮點型、集合類型和標識符。將它們放在一起介紹是因為它們的實現方法類似。
因為它們的實現都用到了ReadValue方法,因此先來介紹ReadValue方法的實現:
function TReader.ReadValue: TValueType;
begin
Read(Result, SizeOf(Result));
end;
該方法調用私有方法Read,從Reader對象流中讀一個字節,並移動位置指針。
ReadValue方法專門從流中讀取值的類型的,所有的數據讀寫方法中在讀取數據前都要調用ReadValue方法判斷是否是所要讀的數據。如果是,則調用Read方法讀取數據;否則觸發一個異常事件,下面看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;
因為Delphi 2.0中,整型可分8位、16位和32位,因此讀取整型數據時分別作了判斷。
布爾類型的數據是直接放在值類型標志上,如果類型為VaTrue,則值為True;如果類型為VaFalse,則值為False。
function TReader.ReadBoolean: Boolean;
begin
Result := ReadValue = vaTrue;
end;
ReadString方法也利用ReadValue方法判斷是字符串還是長字符串。
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類型緊接著一個字節存有字符串的長度;如果是VaLString類,則緊接著兩個字節存放字符串長度,然後根據字符串長度用SetString過程給分配空間,用Read方法讀出數據。
ReadFloat方法允許將整型值轉換為浮點型。
function TReader.ReadFloat: Extended;
begin
if ReadValue = vaExtended then Read(Result, SizeOf(Result)) else
begin
Dec(FBufPos);
Result := ReadInteger;
end;
end;
字符類型數據設有直接的標志,它是根據VaString後面放一個序值為1的字節來判斷的。
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文件需要,Filer對象支持讀取標識符。
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;
一般說來,各種復雜的數據結構都是由這些簡單數據組成;定義了這些方法等於給讀各種類型的數據提供了元操作,使用很方便。例如,讀取字符串類型的數據時,如果采用傳流方法還要判斷字符串的長度,使用ReadString方法就不同了。但應該特別注意的是這些類型數據的存儲格式是由Delphi設計的與簡單數據類型有明顯的不同。因此,存入數據時應當使用Writer對象相應的方法,而且在讀數據前要用NextValue方法進行判斷,否則會觸發異常事件。