[英]Writing tList<string> to tFileStream
我在Windows 10中使用Berlin。我嘗試將tList<string>
保存到文件中。
我知道如何處理tStringlist,tStreamWriter和tStreamReader,但是我需要使用tFileStream,因為應該添加其他類型的數據。
在下面的代碼中,讀取數據的Button2Click循環引發eOutOfMemory異常。 當我將簡單的字符串值分配給_String時,效果很好,但是如果我將tList值分配給相同的_String,則似乎在文件上寫入了錯誤的數據。 我不明白_String := _List.List[i]
和_String := 'qwert'
之間的區別。
如何將tList<string>
寫入tFileSteam?
procedure TForm1.Button1Click(Sender: TObject);
var
_List: TList<string>;
_FileStream: TFileStream;
_String: string;
i: Integer;
begin
_List := TList<string>.Create;
_List.Add('abcde');
_List.Add('abcde12345');
_FileStream := TFileStream.Create('test', fmCreate);
for i := 0 to 1 do
begin
_String := _List.List[i]; // _String := 'qwert' works well
_FileStream.Write(_string, 4);
end;
_FileStream.Free;
_List.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
_FileStream: TFileStream;
_String: string;
i: Integer;
begin
_FileStream := TFileStream.Create('test', fmOpenRead);
for i := 0 to 1 do
begin
_FileStream.Read(_String, 4);
Memo1.Lines.Add(_String);
end;
_FileStream.Free;
end;
如果您在文檔中查找TFileStream.Write
功能,它將告訴您(從THandleStream.Write
繼承):
function Write(const Buffer; Count: Longint): Longint; override; function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; override;
將Buffer的Count字節寫入資源中的當前位置。
現在, Buffer
是無類型的,因此應該是要寫入的數據的內存地址。 您正在傳遞一個字符串變量,該變量是對實際字符串數據的引用,該變量的地址包含指向字符串數據的指針。 因此,您正在編寫一個指向文件的指針。
要更正它,請將字符串的第一個字符傳遞給緩沖區, ....write(_string[1], ...
如果您具有編譯器指令{$ ZEROBASEDSTRINGS ON},則應使用索引0。或者,將字符串鍵入PChar
和取消引用它: ....write(PChar(_String)^, ...
然后查看第二個參數Count
。 正如文檔所說,它表示要寫入的字節數,而不是字符。 在Delphi 2009及更高版本中,字符串為UnicodeString
,因此每個字符為2個字節。 您需要傳遞字符串大小(以字節為單位)。
這會將4個字符(8個字節)寫入文件流:
_FileStream.Write(_String[1], 4 * SizeOf(Char));
或更好
_FileStream.Write(PChar(_String)^, 4 * SizeOf(Char));
對於閱讀,您需要進行相應的更改,但最值得注意的是,您需要在閱讀之前設置字符串的長度(長度以字符為單位)。
SetLength(_String, 4);
for i := 0 to 1 do
begin
_FileStream.Read(_String[1], 4 * SizeOf(Char));
Memo1.Lines.Add(_String);
end;
要繼續這種低級方法,您可以按如下方式概括字符串的讀寫:添加一個變量以保存字符串的長度
var
_String: string;
_Length: integer;
然后寫
begin
...
for ....
begin
_String := _List.List[i];
_Length := Length(_String);
_FileStream.Write(_Length, SizeOf(Integer));
_FileStream.Write(PChar(_List.List[i])^, _Length * SizeOf(Char));
end;
和閱讀
begin
...
for ....
begin
_FileStream.Read(_Length, SizeOf(Integer));
SetLength(_String, _Length);
_FileStream.Read(_String[1], _Length * SizeOf(Char));
Memo1.Lines.Add(_String);
end;
IOW,您先寫長度,然后寫字符串。 閱讀時,您先讀取長度,然后讀取字符串。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.