动态数组的BlockRead和BlockWrite

时间:2016-11-03 11:59:53

标签: delphi dynamic file-io

我正在尝试组织保存和加载大小不一的数据。因此,保存文件需要存储多个(未知且每次不同数量)的动态数组。

此MCVE中出现错误:

procedure TAnnMainF.Button6Click(Sender: TObject);
var
  f: file;
  ari, aro: array of double;
  i, Count: word;
begin
  SetLength(aro, random(5) + 1);
  for i := 0 to High(aro) do
    aro[i] := random(2001) / 2000 - 1;

  AssignFile(f, 'c:\delme\1.txt');
  ReWrite(f);
  Count := Length(aro);
  BlockWrite(f, Count, SizeOf(word));
  BlockWrite(f, aro[0], SizeOf(double) * Count);
  CloseFile(f);

  Reset(f);
  BlockRead(f, Count, SizeOf(word));
  BlockRead(f, ari[0], SizeOf(double) * Count);
  CloseFile(f);
end;

此代码导致I / O错误998。 我试图声明类型TDoubleArray = array of Double;并将ari作为参数传递给BlockRead。在我调用BlockRead之前,我还试过SetLength(ari, Count)但没有成功。

Answer to this question没有帮助我。 代码正确读取Count但在数组加载时引发异常。 我做错了什么?

1 个答案:

答案 0 :(得分:5)

您必须在重写/重置命令中设置块的大小:

ReWrite(f,1);
...
Reset(f,1);

来自documentation

  

RecSize是一个可选表达式,仅当F是无类型文件时才能指定。如果F是无类型文件,则RecSize指定要在数据传输中使用的记录大小。如果省略RecSize,则假定默认记录大小为128字节。

这意味着读取数据将溢出分配的缓冲区,从而导致系统的I / O错误。

另请阅读此warning about using ancient file I/O BlockRead/BlockWrite

  

警告:这是一种较旧的方法,由于无类型的Buf参数,使用起来特别危险,导致潜在的内存损坏。 BlockRead和BlockWrite使用的记录大小由用于打开正在写入的文件的Reset或Rewrite调用的可选第二个参数控制。最好在您的应用程序中使用流。例如,涉及流的用户过程可以使用TMemoryStreamsTFileStreams,而不是像使用这些较旧的例程一样使用文件。

一般来说,BlockRead/Write和流之间的速度差异无关紧要。对于较大的文件,首选缓冲处理程序。

David提供了一个优秀的缓冲文件流处理程序示例:Buffered files (for faster disk access)

正如@kami / @ TomBrunberg所说,你尝试了什么,你还必须在读取数据之前分配ari动态数组的长度。