Ich habe eine Datei .\input.txt
wie diese:
aaa
bbb
ccc
Wenn ich es mit lese TStrings.LoadFromFile
und zurückschreibe (auch ohne Änderungen vorzunehmen) TStrings.SaveToFile
, wird am Ende der Ausgabedatei eine leere Zeile erstellt.
var
Lines : TStrings;
begin
Lines := TStringList.Create;
try
Lines.LoadFromFile('.\input.txt');
//...
Lines.SaveToFile('.\output.txt');
finally
Lines.Free;
end;
end;
Das gleiche Verhalten kann mit der TStrings.Text
Eigenschaft beobachtet werden, die eine Zeichenfolge zurückgibt, die am Ende eine leere Zeile enthält.
delphi
tstringlist
Fabrizio
quelle
quelle
\n
Zeichen endet und die Funktion das\n
der Datei hinzufügt ? Oder fügt die Funktion buchstäblich ein\n
Recht nach einem\n
am Ende der Datei vorhandenen hinzu? Für POSIX müssen Textdateien alle Zeilen mit einem\n
, nur zu Ihrer Information, abgeschlossen haben. Es wurde viel Software geschrieben, um einigen Standards zu entsprechen. Aus diesem Grund fügen viele Redakteure die fehlende Terminierung hinzu,\n
wenn Sie Dateien standardmäßig speichern (z. B.vim
IDEs usw. machen Ihre Dateien standardmäßig POSIX-konform.)Antworten:
Für Delphi 10.1 und höher gibt es eine Eigenschaft
TrailingLineBreak
die dieses Verhalten steuert.quelle
TrailingLineBreak
Eigenschaft sicherlich gerne nutzen, sobald ich die IDE aktualisiere. +1 und akzeptiertFür Delphi 10.1 (Berlin) oder neuer wird die beste Lösung in Uwes Antwort beschrieben.
Für ältere Delphi-Versionen habe ich eine Lösung gefunden, indem ich eine untergeordnete Klasse
TStringList
derTStrings.GetTextStr
virtuellen Funktion erstellt und diese überschrieben habe. Ich bin jedoch froh zu wissen, ob es eine bessere Lösung gibt oder ob jemand anderes in meiner Lösung einen Fehler gefunden hatSchnittstelle:
Implementierung:
Beispiel:
quelle
SetLength(Result, -2)
.GetTextStr
, wennLength(Result)
ist0
, dann tun SieSetLength(Result, -2)
, das ist schlecht. Es mag sein, dass der Effekt der gleiche ist wieSetLength(Result, 0)
, aber ich kenne keine Garantie dafür. Zumindest die offizielle Dokumentation enthält keine solche Garantie. (Theoretisch könnten also schlimme Dinge passieren.)Length(Result) = 1
ja, dann tust du dasSetLength(Result, -1)
, was genauso schlimm ist! Außerdem kann es sein, dassResult
dies nicht mit einem Zeilenumbruch endet. In diesem Fall entfernen Sie die beiden letzten Zeichen aus der letzten Zeile. Das ist auch ein Fehler. (Und das kann zum Beispiel passieren, wenn Sie es verwendenTrailingLineBreak
, vermute ich. Auch wenn nicht, kann es andere Instanzen geben.) Sie sollten wirklich testen, ob die Zeichenfolge wirklich mit einem Zeilenumbruch endet, wie zif not IncludeLastLineBreakInText and Result.EndsWith(LineBreak) then
.Pos(LineBreak, Result) = Length(Result) - Length(LineBreak) + 1
.Pos
Gibt den Index der ersten Übereinstimmung an. Wenn Ihre Zeichenfolge 6 Zeilenumbrüche enthält, wird die Position der ersten angegeben, aber Sie erwarten eindeutig die letzte eins ...