Search code examples
delphifile-iotext-fileslazarusfpc

Best way for read and write a text file


I am using the latest version of Lazarus IDE and I have a Memo1 on my TForm1. I have to load a text file in Memo1 and then edit every line of the Memo (I use Memo1.Lines.Strings[i] := ...). At the end I must save the edited memo at a particular path.

Question: I am looking for the faster way between:

  1. Load the whole text inside the memo, edit its content and save into a new file (load all -> edit all -> write all)
  2. Do a while loop (until the end of my *.txt file) that reads the file line by line, edit the content and save it in the new file. (load line -> edit -> write | load -> edit -> write | load line -> edit -> write | ...)

I am pretty new with Delphi developing, and I have also read some pages about TStringLists. My text file is going to have a lot of lines (It could have 5000+ lines) and I don't want that my program loses performance.

Any suggestion? Should I use TStringList or one of the two methods I listed before?


Solution

  • 5000 lines isn't a lot, unless the strings are very long.

    The easiest way is to use a TStringList. There's no need to use a GUI control unless the user needs to see or edit the content.

    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;
    

    If (as you say in a comment above) you need to do this in a TMemo for testing purposes, you can do it the same way:

    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);
    

    Of course, the easiest way to do this would be to write a procedure that accepts a plain TStrings descendent of any sort:

    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; 
    

    Then you can call it with either one:

    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);