读写文本文件的最佳方法

5
我正在使用最新版本的Lazarus IDE,我的TForm1上有一个Memo1。我必须在Memo1中加载文本文件,然后编辑每行Memo(我使用Memo1.Lines.Strings[i] := ...)。最后,我必须将编辑后的Memo保存到特定路径。
问题:我正在寻找以下两种方法之间的更快方法:
1.将整个文本加载到Memo中,编辑其内容并保存到新文件(全部加载-编辑全部-写入全部);
2.执行一个while循环(直到我的*。txt文件结束),逐行读取文件,编辑内容并将其保存在新文件中(加载行-编辑-写入|加载-编辑-写入|加载行-编辑-写入|...)。
我对Delphi开发还相当陌生,并且我还阅读了一些关于TStringLists的页面。我的文本文件将有许多行(可能有5000多行),我不想使我的程序失去性能。
您有什么建议吗?我应该使用TStringList还是前面列出的两种方法之一?

1
你是在备忘录中编辑(实际上是输入以修改文本)吗?如果是这样,只需加载、编辑和保存即可。如果不是,则使用 TStringList,因为您不需要 GUI 控件的开销。 - Ken White
1
在GUI控件中加载一些数据却不做任何与GUI相关的操作,这样做有点傻吗?你觉得呢? - Free Consulting
我这么做是因为我必须看看程序在循环中做了什么。我知道你的意思,但这只是我为我的程序测试的一个“特性”。无论如何,感谢你的建议。 - Alberto Miola
我认为检查成千上万行文本并不是测试某个操作的好方法。真正的建议是:确保你有 filesize * 2 字节的空闲内存来利用 TStrings 的使用,否则交换会使其比逐行读取慢得多。 - Free Consulting
将额外的符号插入字符串的中间会迫使不停地在内存中复制其余的文本,随着N的增加呈N平方级增长。更快的代码应该是使用新的TStringBuilder(带有内存预分配)或从源数据中创建ArrayOfString。然而,在这种情况下,HDD的读写速度限制比RAM的读写速度限制更严格。 - Arioch 'The
显示剩余3条评论
1个回答

10

5000 行并不算多,除非字符串非常长。

最简单的方法是使用 TStringList。除非用户需要查看或编辑内容,否则无需使用 GUI 控件。

var
  SL: TStringList;
  i: Integer;
begin
  SL := TStringList.Create;
  try
    SL.LoadFromFile(YourFileNameHere);
    for i := 0 to SL.Count - 1 do
    begin
      SL[i] := IntToStr(i) + ' ' + SL[i];
      // Do any other processing
    end;

    SL.SaveToFile(YourFileNameHere);
  finally
    SL.Free;
  end;
end;

如果您需要在TMemo中进行测试,可以按照以下方式进行:

Memo1.Lines.LoadFromFile(YourFileNameHere);
for i := 0 to Memo1.Lines.Count - 1 do
  Memo1.Lines[i] := IntToStr(i) + ' ' + Memo1.Lines[i];
Memo1.Lines.SaveToFile(YourFileNameHere);

当然,最简单的方法是编写一个接受任何类型的普通 TStrings 子类的过程:
procedure AppendValueToStrings(const SL: TStrings; 
  StartingValue: Integer);
var
  i: Integer;
begin
  Assert(Assigned(SL));  // Make sure a valid TStrings has been passed in
  for i := 0 to SL.Count - 1 do
  begin
    SL[i] := IntToStr(StartingValue) + ' ' + SL[i];
    Inc(StartingValue);
  end;
end; 

然后你可以使用其中任意一种方式调用它:

SL := TStringList.Create;
try
  SL.LoadFromFile(YourFileNameHere);
  AppendValueToStrings(SL, 10);
  SL.SaveToFile(YourFileNameHere);
finally
  SL.Free;
end;

Memo1.Lines.LoadFromFile(YourFileNameHere);
AppendValueToStrings(Memo1.Lines, 10);
Memo1.Lines.SaveToFile(YourFileNameHere);

谢谢你,你解决了我的问题。我要接受了。只是一个问题:我学习到在 for 循环中必须用 begin-end 包围代码。不是这样吗? - Alberto Miola
除非您有多行代码将在“for”循环中执行,否则您不需要这样做。我通常会在自己的代码中这样做,因为我通常有多行运行。如果您不确定,最好使用它们。我会编辑以添加它们,这是一个更好的习惯。 - Ken White
好的,那段代码只有一行,我可以省略begin-end。再次感谢你 ;) - Alberto Miola

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接