首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将tList<string>写入tFileStream

将tList<string>写入tFileStream
EN

Stack Overflow用户
提问于 2016-08-27 09:48:21
回答 1查看 962关注 0票数 1

我在Windows 10中使用柏林,我试图将tList<string>保存到一个文件中。

我知道如何处理tStringlist、tStreamWriter和tStreamReader,但是我需要使用tFileStream,因为应该添加其他类型的数据。

在下面的代码中,读取数据的Button2Click循环会引发eOutOfMemory异常。当我将简单的字符串值分配给_String时,它工作得很好,但是如果我将tList值放在同一个_String上,那么文件上似乎写入了错误的数据。我不明白_String := _List.List[i]_String := 'qwert'之间的区别。

我如何将tList<string>写到tFileSteam?

代码语言:javascript
复制
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;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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个字节):

代码语言:javascript
复制
_FileStream.Write(_String[1], 4 * SizeOf(Char));

或者更好

代码语言:javascript
复制
_FileStream.Write(PChar(_String)^, 4 * SizeOf(Char));

对于读取,您需要进行相应的更改,但最值得注意的是,您需要在读取之前设置字符串长度(长度以字符计算)。

代码语言:javascript
复制
  SetLength(_String, 4);
  for i := 0 to 1 do
  begin
    _FileStream.Read(_String[1], 4 * SizeOf(Char));

    Memo1.Lines.Add(_String);
  end;

要继续这种低级别的方法,您可以将字符串写入和读取概括如下:添加一个变量以保存字符串的长度。

代码语言:javascript
复制
var
  _String: string;
  _Length: integer;

然后写

代码语言:javascript
复制
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;

和阅读

代码语言:javascript
复制
begin
  ...
  for ....
  begin
    _FileStream.Read(_Length, SizeOf(Integer));
    SetLength(_String, _Length);
    _FileStream.Read(_String[1], _Length * SizeOf(Char));
    Memo1.Lines.Add(_String);
  end;

IOW,你先写长度,然后写字符串。在读取时,您读取长度,然后读取字符串。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39179714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档