delphi 使用 TStreamReader 和 TStringList 处理非常大的文本文件  
官方Delphi 学习QQ群: 682628230(三千人)
频道

delphi 使用 TStreamReader 和 TStringList 处理非常大的文本文件


我正在使用 Embarcadero 的 Rad Studio Delphi (10.2.3) 并且在读取非常大的文本文件时遇到了内存问题(700 万行以上,每一行都不同,行的长度可以是 1 到 ~200 个字符等)。我是 Delphi 编程的新手,所以我在发帖之前搜索了 SO 和 Google 以寻求帮助。

我最初实现了一个 TStringList 并使用 LoadFromFile 方法读取文件,但是当处理的文本文件变得足够大时,这失败了。然后我实现了一个 TStreamReader 并使用 ReadLn 使用这里找到的基本代码来填充 TStringList:


代码示例:

//MyStringList.LoadFromFile(filename);Reader := TStreamReader.Create(filename, true);try
 MyStringList.BeginUpdate;
 try
   MyStringList.Clear;
   while not Reader.EndOfStream do
     MyStringList.Add(Reader.ReadLine);
 finally
   MyStringList.EndUpdate;
 end;finally
 Reader.Free;end;


这很有效,直到我需要处理的文件变得巨大(约 700 万行 +)。看起来 TStringList 变得如此之大,以至于耗尽了内存。我说“出现”是因为我实际上无法访问正在运行的文件,并且所有错误信息都是我的客户通过电子邮件提供的,这使得这个问题更加困难,因为我不能简单地在 IDE 中对其进行调试.

代码是 32 位编译的,我无法使用 64 位编译器。我也不能包括数据库系统等。不幸的是,我有一些严格的限制。我需要加载每一行以查找模式并将这些行与其他行进行比较以查找“模式中的模式”。我很抱歉在这里非常含糊。

最重要的是 - 有没有办法在不使用 TStringList 的情况下访问文本文件中的每一行,或者可能有更好的方法来处理 TStringList 内存?

也许有一种方法可以将 StreamReader 中的特定行块加载到 TStringList 中(例如,读取前 100,000 行并处理、接下来的 100,000 行等)而不是一次加载所有内容?我想我可以写一些东西来处理可能的“块间”模式。

在此先感谢您的任何帮助和建议!

***** 使用更新进行编辑 *****

好的,这是我需要实施的基本解决方案:

var
 filename: string;
 sr: TStreamReader;
 sl: TStringList;
 total, blocksize: integer;begin
 filename := 'thefilenamegoeshere';
 sl := TStringList.Create;
 sr := TStreamReader.Create(filename, true);
 sl.Capacity := sr.BaseStream.Size div 100;
 total := 0; // Total number of lines in the file (after it is read in)
 blocksize := 10000; // The number of lines per "block"
 try
   sl.BeginUpdate;
   try
     while not sr.EndOfStream do
       begin
         sl.Clear;
         while not (sl.Count >= blocksize) do
           begin
             sl.Add(sr.ReadLine);
             total := total + 1;
             if (sr.EndOfStream = true) then break;
           end;
         // Handle the current block of lines here
       end;
   finally
     sl.EndUpdate;
   end;
 finally
   sr.Free;
   sl.Free;
 end;end;

我有一些测试代码可用于改进我的例程,但这似乎相对快速、高效且足够。我要感谢每个人的反应,让我的灰质燃烧起来!



推荐分享
图文皆来源于网络,内容仅做公益性分享,版权归原作者所有,如有侵权请告知删除!
 

Copyright © 2014 DelphiW.com 开发 源码 文档 技巧 All Rights Reserved
晋ICP备14006235号-8 晋公网安备 14108102000087号

执行时间: 0.086122989654541 seconds