我正在使用 Embarcadero 的 Rad Studio Delphi (10.2.3),并且在读取非常大的文本文件(700 万行以上,每行都不同,行长度可以是 1 到 ~200 个字符等)时遇到内存问题.)。我对 Delphi 编程相当陌生,所以在发帖之前我已经搜索过 SO 和 Google 寻求帮助。
我最初实现了一个 TStringList 并使用 LoadFromFile 方法读取文件,但是当处理的文本文件变得足够大时,这会失败。然后,我实现了一个 TStreamReader 并使用 ReadLn 使用此处找到的基本代码填充 TStringList:
TStringList.LoadFromFile - Exceptions with Large Text Files
代码示例:
//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 中的特定行 block 加载到 TStringList 中(例如,读取前 100,000 行并处理,接下来的 100,000 行等),而不是一次加载所有内容?我想我可以写一些东西来处理可能的“ block 间”模式。
预先感谢您的任何帮助和建议!
***** 已编辑并更新 *****
好的,这是我需要实现的基本解决方案:
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;
我有一些测试代码,我将用它们来完善我的例程,但这似乎相对快速、高效且足够。我要感谢大家的回应,让我的灰质兴奋不已!
最佳答案
作为(非常)快速的修复,您可以尝试使用https://github.com/Zeus64/alcinoe中的TALStringlist(只需在代码中将TStringList替换为TalStringList) 。这不是一个非常干净的方法,但 TALStringlist 将保留在 unicode UTF-8 中,将默认 UTF 16 字符串使用的内存减少 2。由于您有 7 000 000 行,大约 100 个字符,这意味着大约 700 Mb,这可以在 32 位上运行
关于delphi - 使用 TStreamReader 和 TStringList 处理非常大的文本文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52856829/