动态数组的BlockRead和BlockWrite

asd*_*-tm 0 delphi file-io dynamic

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

这个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;
Run Code Online (Sandbox Code Playgroud)

此代码导致I/O错误998.我试图声明类型 TDoubleArray = array of Double;ari在BlockRead中作为参数传递.SetLength(ari, Count)在我调用BlockRead之前我也尝试过没有任何成功.

这个问题答案对我没有帮助.代码读取Count正确,但在数组加载时引发异常.我究竟做错了什么?

LU *_* RD 5

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

ReWrite(f,1);
...
Reset(f,1);
Run Code Online (Sandbox Code Playgroud)

来自文档:

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

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

另请阅读有关使用古代文件I/O BlockRead/BlockWrite的警告:

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

通常BlockRead/Write,流与流之间的速度差异是微不足道的.对于较大的文件,首选缓冲处理程序.

David提供了一个缓冲文件流处理程序的绝佳示例:缓冲文件(用于更快的磁盘访问)


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