Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 在Delphi中插入二进制文件中间的记录_File_Delphi_Binary_Pascal_Records - Fatal编程技术网

File 在Delphi中插入二进制文件中间的记录

File 在Delphi中插入二进制文件中间的记录,file,delphi,binary,pascal,records,File,Delphi,Binary,Pascal,Records,我正在用Delphi创建一个程序,我需要在一个二进制文件中插入一条记录,但要在两条现有记录之间插入。有人能帮我吗?如果你真的想插入,那么你必须用不同的名称创建一个新文件,将旧文件内容复制到新文件,直到插入点,然后将新记录写入新文件,最后将旧文件的其余部分复制到新文件。然后删除旧文件并将新文件重命名为旧文件的名称 原始文件: [A][B][C][D][E][F][G][H] ^ insertion point 插入点之前的第一次复制内容: [A]

我正在用Delphi创建一个程序,我需要在一个二进制文件中插入一条记录,但要在两条现有记录之间插入。有人能帮我吗?

如果你真的想插入,那么你必须用不同的名称创建一个新文件,将旧文件内容复制到新文件,直到插入点,然后将新记录写入新文件,最后将旧文件的其余部分复制到新文件。然后删除旧文件并将新文件重命名为旧文件的名称

原始文件:

[A][B][C][D][E][F][G][H]
            ^
            insertion point 
插入点之前的第一次复制内容:

[A][B][C][D]
写新记录:

[A][B][C][D][Z]
[A][B][C][D][Z][E][F][G][H]
            ^  <---------->
然后复制其余部分:

[A][B][C][D][Z][E][F][G][H]
如果您只想替换记录,请查看随机访问I/O,可以使用旧的Pascal
Seek
BlockRead
/
BlockWrite
,也可以使用流
TStream.Seek
TStream.Write
。后者是更现代的做事方式

更新 正如注释中所建议的,您还可以执行以下操作(使用与上述相同的例程):

打开文件进行读写,将文件大小增加到要插入的记录的大小,将插入点“上方”的内容移动到更高的文件“地址”,然后将记录写入插入点

之前:

[A][B][C][D][E][F][G][H]
            ^
            insertion point 
然后向上移动E:

[A][B][C][D][E][E][F][G][H]
            ^  <---------->
[A][B][C][D][E][E][F][G][H]
^  
最后写下新记录:

[A][B][C][D][Z]
[A][B][C][D][Z][E][F][G][H]
            ^  <---------->
[A][B][C][D][Z][E][F][G][H]
^  
如果您想以块的形式复制内容(比如,4k块),那么不要忘记向后复制(从高文件指针到低文件指针),这样您就不会覆盖尚未阅读的内容。或者使用双缓冲区。或者



你可以随心所欲地把事情弄复杂。我个人可能会复制到一个新文件,删除旧文件并重命名新文件,然后处理它。

这种方法基本上与在数组中插入元素的方法完全相同。注意,它依赖于大小相同的记录

  • 从文件中读取下一条记录以备以后使用
  • 用新记录覆盖下一条记录
  • 向前移动“插入位置”1记录
  • 从1开始重复,将先前读取的记录视为要插入的记录

  • 我不会说复制,因为您谈论的是二进制数据,但想法与此相同:您在任务的哪些方面遇到困难?我不建议使用这种方法。为什么?因为在硬盘上,这将导致糟糕的性能,因为您将执行许多小型读写操作。虽然在SSD上,性能下降不会如此明显,但可能会增加SSD的磨损。为什么?因为与传统硬盘不同的是,SSD需要一次性重写整个数据单元,传统硬盘可以写入每个字节。所以我必须承认鲁迪的答案是更好的。你不需要创建一个新文件。对于新插入的记录大小,最好增加文件的大小。将插入点后的文件内容临时复制到内存中。将新记录写入文件,然后从内存中写入文件的其余复制内容。这避免了创建新文件和将文件的全部内容(分两步)从一个位置复制到另一个位置的需要。如果文件大小太大,插入点后的数据可以立即存储在内存中,您仍然可以分块执行此操作。我总是担心将整个文件(特别是如果文件很大)复制到内存中。是的,您可以增加大小,将插入点后的内容复制到“更高”的文件位置(以块或整体形式),然后“插入”记录。但我不确定这是否更有效。我会按我的方式去做。请注意,如果您是分块复制的,则必须向后工作,以避免覆盖尚未阅读的内容,或者保留一个双缓冲区。嗯,还有什么更快的方法?例如,在插入点之后读取1 GB数据,然后在插入记录之后将其写回,或者分两步复制2 GB数据(一步用于插入点之前的数据,另一步用于插入点之后的数据)。如果必须将数据移动成一堆小数据块,我的方法只会更慢。至于你的方法,它也有一个很大的缺点。什么缺点?您需要足够的磁盘空间来实际复制现有文件。所以,如果原始文件的大小是2GB,那么您还需要2GB的免费空间space@SilverWarior第二种方法会更快,但如果中间有人出了问题,则会导致文件损坏。第一种方法速度较慢,但安全—在创建正确的新文件之前,它从不销毁旧文件,因此,如果出现问题,用户至少会拥有旧数据,而使用更快的方法,他既不会拥有旧数据,也不会拥有新数据。@SilverWarrior:在我原来的情况下,旧文件只会被读取,很可能不会被破坏。