我正在使用 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