Delphi Pascal - 如何将大于2GB的数据写入文件?

15

我用Delphi制作了一个生成彩虹表的工具。一切都好,直到文件增长到3.1GB。我关闭了程序。然后我重新打开它,但在执行以下代码时崩溃:

Assign(RainbowFile,'Rainbow_table.txt'); {assign a text file}
Append(RainbowFile);

Delphi显示错误"raised expection class EInOutError with message 'I/O error 131'。 我的问题是:如何向大于2 GB的现有文件追加数据。 // 已过时 下一个问题: 我目前有以下代码:

   Content_to_file := (#13+#10+Start_string+':'+hexstr(GTA_San_Andreas_CRC32(Start_string), 8));
   RainbowFile_handle.WriteBuffer( Content_to_file[1], Length(Content_to_file)*SizeOf(Char));
如何摆脱 Content_to_file 变量。如果可能的话,我想直接将其放入 WriteBuffer 中。
编辑:
TFileStream 可以处理大于 2GB 的文件。我现在已经测试过了。 不过是否可能这样写:
RainbowFile_handle.WriteBuffer( Start_string[1]+':', 

我的意思是不传递任何变量参数。或者我一定要传递变量的第一个字符吗?

编辑2:

我目前是这样做的:

    Content_to_file := (#13+#10+Start_string+':'+hexstr(GTA_San_Andreas_CRC32(Start_string), 8));
    RainbowFile_handle.WriteBuffer( Content_to_file[1], Length(Content_to_file)*SizeOf(Char));

不使用这个变量是否有可能实现?


2
你的文件系统支持大于2GB的文件吗? - Satya
是的,它有。我使用的是Windows XP 32位操作系统。目前文件大小为3.1 GB,存储在我的NTFS分区中。问题出在我的Pascal代码上。 - fastman92
2个回答

25
你应该转换为流操作。使用TFileStream可以轻松处理此问题。请注意,如果您使用随机访问,则必须确保使用64位版本的SeekPosition

打开文件流后,你可以寻找到文件末尾:

Stream.Seek(0, soEnd);

那么你可以这样写:

procedure StreamWriteLine(Stream: TFileStream; Text: string);
begin
  Text := Text + sLineBreak;
  Stream.WriteBuffer(Text[1], Length(Text)*SizeOf(Char));
end;

希望这能给你足够的线索来填写其余的细节。


下一个显而易见的问题是如何向流写入多个参数。我只在需要时才需要流的原因之一。 - Marco van de Voort
@Marco,编写这样的例程并将其封装在现有的流类中不是什么麻烦。我个人倾向于不直接使用Delphi提供的流类,而是喜欢使用自己的子类版本,以增加额外的功能来满足我的需求。特别是我有一个用于性能原因进行I/O缓冲的文件流,还有一个分配块内存而不是要求连续内存的内存流。 - David Heffernan
那我真的很想看到。Write(lN)使用编译器魔法。也许有一些方法可以通过搞乱textrec系统来解决,但如果你这样做,你最好直接解决64位问题。在我看来,流对于文本文件来说并不是非常舒适的。 - Marco van de Voort
@Marco,我希望你能够像Format函数一样,利用const Args: array of const做一些有用的事情。 - David Heffernan
我记得我曾经尝试过,但它似乎不会进行真正的格式化,你会在某些类型的表达式上出现错误,需要添加[]。当时我时间紧迫,最终放弃了。但让我困惑的是,为什么没有标准化组件被添加。这向我发出信号表明它并不是真正被弃用,只是表明E.认为2GB的文本文件是一个糟糕的想法。 - Marco van de Voort
显示剩余2条评论

8

传统的过程式I/O已经不适合现代操作。只需使用TFileStream类,或者如果需要精细控制,则直接使用Windows API(请阅读有关CreateFileWriteFile函数的信息)。


2
“纯过程输入/输出(I/O)不适用于现代操作。”你所说的这些所谓的“现代操作”是什么? - dummzeuch
3
@dummzeuch 写入超过2GB的数据是一个完全有效的现代操作,读取也同样如此。 - Eugene Mayevski 'Callback
2
@Marco 我认为他们想要让那些函数过时,而不是“修复”它们。 - Eugene Mayevski 'Callback
6
作为一个等待64位支持已经超过5年的人,例如,如果Embarcadero花时间“修复”过时的陈旧遗留例程而不是让Delphi保持最新状态,我会非常失望。@Marco @Eugene - David Heffernan
1
@David +1。CodeGear 有更重要的事情要做,而不是修复 25 多年前的程序。 - Eugene Mayevski 'Callback
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接