我在Windows 10中使用柏林,我试图将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;发布于 2016-08-27 18:27:16
如果您在文档中查找TFileStream.Write所做的事情,它将告诉您(从THandleStream.Write继承):
函数写入(const缓冲器;计数: Longint):Longint;覆盖;函数写(const缓冲区: TBytes;偏移量,计数: Longint):Longint; 将计数字节从缓冲区写入资源中的当前位置。
现在,Buffer是非类型化的,因此应该是要写入的数据的内存地址。您正在传递一个字符串变量,它是对实际字符串数据的引用,该变量的地址保存一个指向字符串数据的指针。因此,您正在写入指向该文件的指针。
要更正它,首先传递缓冲区的字符串,如果您有编译器指令{$ZEROBASEDSTRINGS ON},请使用索引0。或者,将字符串键入到PChar并取消它的引用:....write(PChar(_String)^, ...
然后看第二个参数,Count。正如文档所述,它指示要写入的字节的数量,特别是字符。在Delphi2009和更高版本的字符串中是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,你先写长度,然后写字符串。在读取时,您读取长度,然后读取字符串。
https://stackoverflow.com/questions/39179714
复制相似问题