我正在尝试组织保存和加载大小不一的数据。因此,保存文件需要存储多个(未知且每次不同数量)的动态数组。
此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
但在数组加载时引发异常。
我做错了什么?
答案 0 :(得分:5)
您必须在重写/重置命令中设置块的大小:
ReWrite(f,1);
...
Reset(f,1);
RecSize是一个可选表达式,仅当F是无类型文件时才能指定。如果F是无类型文件,则RecSize指定要在数据传输中使用的记录大小。如果省略RecSize,则假定默认记录大小为128字节。
这意味着读取数据将溢出分配的缓冲区,从而导致系统的I / O错误。
另请阅读此warning about using ancient file I/O BlockRead/BlockWrite:
警告:这是一种较旧的方法,由于无类型的Buf参数,使用起来特别危险,导致潜在的内存损坏。 BlockRead和BlockWrite使用的记录大小由用于打开正在写入的文件的Reset或Rewrite调用的可选第二个参数控制。最好在您的应用程序中使用流。例如,涉及流的用户过程可以使用TMemoryStreams和TFileStreams,而不是像使用这些较旧的例程一样使用文件。
一般来说,BlockRead/Write
和流之间的速度差异无关紧要。对于较大的文件,首选缓冲处理程序。
David提供了一个优秀的缓冲文件流处理程序示例:Buffered files (for faster disk access)
正如@kami / @ TomBrunberg所说,你尝试了什么,你还必须在读取数据之前分配ari
动态数组的长度。