Как предотвратить создание TStrings.SaveToFile окончательной пустой строки? - PullRequest
8 голосов
/ 17 октября 2019

У меня есть файл .\input.txt, например:

aaa
bbb
ccc

Если я прочитаю его с помощью TStrings.LoadFromFile и запишу его обратно (даже без применения каких-либо изменений) с помощью 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, которое будетвернуть строку, содержащую пустую строку в конце.

Ответы [ 2 ]

12 голосов
/ 17 октября 2019

Для Delphi 10.1 и новее есть свойство TrailingLineBreak, управляющее этим поведением.

Если свойство TrailingLineBreak имеет значение True (значение по умолчанию), тогда свойство Text будет содержать разрыв строки после последней строки. Если значение равно False, то текстовое значение не будет содержать разрыв строки после последней строки. Это также может контролироваться параметром soTrailingLineBreak.

1 голос
/ 17 октября 2019

Для Delphi 10.1 (Берлин) или новее лучшее решение описано в ответе Уве.

Для более старых версий Delphi я нашел решение, создав дочерний класс TStringList и переопределяя виртуальную функцию TStrings.GetTextStr, но я буду рад узнать, есть ли лучшее решение или кто-то нашел что-то не так в моем решении

Интерфейс:

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