在Delphi中读取大文件的最快方法是什么?

时间:2011-01-06 13:19:25

标签: delphi file-io delphi-2007 tfilestream

我的程序需要从随机访问的巨大二进制文件中读取块。我有一个偏移和长度列表,可能有几千个条目。用户选择一个条目,程序寻找偏移量并读取长度字节。

程序在内部使用TMemoryStream来存储和处理从文件中读取的块。读取数据是通过TFileStream完成的,如下所示:

FileStream.Position := Offset;
MemoryStream.CopyFrom(FileStream, Size);

这很好用,但不幸的是随着文件变大,它变得越来越慢。文件大小从几兆字节开始,但经常达到几十千兆字节。读取的块大小约为100千字节。

文件的内容仅由我的程序读取。它是当时唯一访问该文件的程序。此外,文件也存储在本地,因此这不是网络问题。

我在Windows XP盒子上使用Delphi 2007。

如何加快此文件访问速度?

编辑:

  • 无论正在读取文件的哪个部分,大文件的文件访问速度都很慢。
  • 程序通常不会按顺序读取文件。块的顺序是用户驱动的,无法预测。
  • 从大文件中读取块比从小文件中读取同样大的块总是慢一些。
  • 我说的是从文件中读取块的性能,而不是处理整个文件所需的总时间。对于较大的文件,后者显然需要更长的时间,但这不是问题所在。

我需要向所有人道歉:我按照建议使用内存映射文件实现文件访问后发现它并没有太大的区别。但是在我添加了一些更多的时序代码之后,它也发现它不是文件访问速度会降低程序的速度。无论文件大小如何,文件访问实际上几乎都是恒定的时间。用户界面的某些部分(我尚未确定)似乎存在大量数据的性能问题,并且当我第一次对这些进程进行计时时,我看不出有什么不同。

我很遗憾地发现了瓶颈。

3 个答案:

答案 0 :(得分:3)

如果您打开CreateFile()WinAPI函数的帮助主题,您会在那里找到有趣的标志,例如FILE_FLAG_NO_BUFFERING和FILE_FLAG_RANDOM_ACCESS。你可以和他们一起玩,以获得一些表现。

接下来,复制文件数据,即使是100Kb,也是一个额外的步骤,会减慢操作速度。使用CreateFileMapping和MapViewOfFile函数来获取指向数据的指针是一个好主意。这样您就可以避免复制,也可能获得一定的性能优势(但您需要仔细测量速度)。

答案 1 :(得分:0)

也许你可以采用这种方法:

对最大文件位置的条目进行排序,然后对以下内容进行排序:

  1. 获取只需要文件的第一个X MB的条目(直到某个文件位置)
  2. 将文件中的X MB读入缓冲区(TMemorystream
  3. 现在从缓冲区中读取条目(可能是多线程的)
  4. 对所有条目重复此操作。
  5. 简而言之:缓存文件的一部分并读取所有适合它的条目(multhithreaded),然后缓存下一部分等。

    如果您采用原始方法,也许您可​​以获得速度,但可以根据位置对条目进行排序。

答案 2 :(得分:0)

由于分配内存的方式,Delphi中的TMemoryStream库存很慢。 NexusDB公司拥有更高效的TnxMemoryStream。可能会有一些免费的可以更好地工作。

股票Delphi TFileStream也不是最有效的组件。历史上的Wayback Julian Bucknall在杂志或某个地方发布了名为BufferedFileStream的组件,非常有效地处理文件流。

祝你好运。