如何防止 TStrings.SaveToFile 创建最后一个空行?

How do I prevent TStrings.SaveToFile creating a final empty line?

我有一个这样的文件.\input.txt

aaa
bbb
ccc

如果我使用 TStrings.LoadFromFile and write it back (even without applying any changes) using TStrings.SaveToFile 读取它,它会在输出文件的末尾创建一个空行。

var
  Lines : TStrings;
begin
  Lines := TStringList.Create;
  try
    Lines.LoadFromFile('.\input.txt');

    //...

    Lines.SaveToFile('.\output.txt');
  finally
    Lines.Free;
  end;
end;

使用 TStrings.Text 属性 可以观察到相同的行为,这将 return 一个在末尾包含空行的字符串。

对于 Delphi 10.1(柏林)或更高版本,Uwe 的回答中描述了最佳解决方案。

对于较旧的 Delphi 版本,我通过创建 TStringList and overriding the TStrings.GetTextStr 虚函数的子 class 找到了解决方案,但我很高兴知道是否有更好的解决方案或者是否其他人发现我的解决方案有问题

接口:

  uses
    Classes;

  type
    TMyStringList = class(TStringList)
    private
      FIncludeLastLineBreakInText : Boolean;
    protected
      function GetTextStr: string; override;
    public
      constructor Create(AIncludeLastLineBreakInText : Boolean = False); overload;
      property IncludeLastLineBreakInText : Boolean read FIncludeLastLineBreakInText write FIncludeLastLineBreakInText;
    end;

实施:

uses
  StrUtils;      

constructor TMyStringList.Create(AIncludeLastLineBreakInText : Boolean = False);
begin
  inherited Create;

  FIncludeLastLineBreakInText := AIncludeLastLineBreakInText;
end;

function TMyStringList.GetTextStr: string;
begin
  Result := inherited;

  if(not IncludeLastLineBreakInText) and EndsStr(LineBreak, Result)
  then SetLength(Result, Length(Result) - Length(LineBreak));
end;

示例:

procedure TForm1.Button1Click(Sender: TObject);
var
  Lines : TStrings;
begin
  Lines := TMyStringList.Create();
  try
    Lines.LoadFromFile('.\input.txt');
    Lines.SaveToFile('.\output.txt');
  finally
    Lines.Free;
  end;
end;

对于 Delphi 10.1 和更新版本,有一个 属性 TrailingLineBreak 控制此行为。

When TrailingLineBreak property is True (default value) then Text property will contain line break after last line. When it is False, then Text value will not contain line break after last line. This also may be controlled by soTrailingLineBreak option.