寻求文本文件

时间:2011-01-17 20:35:46

标签: delphi text-files

我正在处理非常大的文本文件,2GB甚至更多。我想有一个类似Seek()的函数。有没有人这样做过?加载到TStringList是不可能的。也使用无类型文件。现在我正在使用readLn,但这持续时间过长。感谢。

5 个答案:

答案 0 :(得分:13)

将文件按片段映射到内存(CreateFileMapping / MapViewOfFile),然后扫描映射的内存并构建索引 - 每行开始的位置列表。然后通过获取文件中第N行的位置并寻找此位置来执行搜索操作。然后使用TFileStream对文件执行随机访问,或者,如果您只读取文件,则可以使用文件映射进行随机访问 - 这可能比使用TFileStream并行文件映射更快。

答案 1 :(得分:3)

尝试GpHugeFile

  

封装Windows文件处理例程,允许使用> 2GB文件。

     

包括支持非缓冲访问(FILE_FLAG_NO_BUFFERING)和缓冲顺序访问的文件。还包括流包装类。

答案 2 :(得分:2)

你设置了一些相当难的边界条件。

我唯一可以想象的是尝试从文本文件中获取句柄,并使用win32函数直接搜索。请注意文本文件缓存。

如果使用writeln / readln的大型代码库是原因,那么实现自己的文本文件驱动程序(或简化缓存)可能就是解决方案。

Free Pascal有一个用于此目的的getfilehandle函数,用于从textfile / tfilerec文件中检索OS句柄。我不知道最近Delphi在这个部门的添加内容。

答案 3 :(得分:2)

如果您需要行级粒度而不是字节级,则绝对无法避免至少读取整个文件一次以找到行标记的结尾(LF或CRLF,具体取决于您的环境)。 )这是一个硬限制 - 你无法事先知道你的终点将会是什么。

在构建行结束到字节偏移量索引之后,您可以将其缓存在磁盘上并使用启发式“la last last time”来检查索引是否需要重新生成(您需要启发式,因为您可以'确保文件内容没有改变,除非通过阅读它,然后你也可以重建索引,因为你仍然会受到I / O限制。)

正如其他人所建议的那样,底层机制必须是CreateFileMapping / CreateViewOfFile(或POSIX下的mmap)。

答案 4 :(得分:1)

您可以使用此功能更改TText文件中的当前位置:

function TextSeek(var f: Text; position: Int64): boolean;
var pos64: Int64Rec absolute position;
    resHi: cardinal;
begin
  result := false;
  with TTextRec(f) do
  begin
    if mode<>fmInput then
      exit;
    resHi := pos64.Hi;
    if (SetFilePointer(handle,pos64.Lo,@resHi,FILE_BEGIN)<>pos64.Lo) or
       (resHi<>pos64.Hi) then
      exit;
    BufEnd := 0; // flush internal reading buffer
    BufPos := 0;
    result := true; // success
  end;
end;

成功时返回true,错误时返回false(未打开文件的无效位置)。

如果您想要快速访问,请确保已设置{$ I-}并手动检查IOResult,并使用一些缓冲区调用System.SetTextBuffer()(1 KB到64 KB可能有意义)。