The TStringList Delphi class can be used to manipulate a list of strings. The TStringList extends TStrings (base class for objects that represent a list of strings). TStrings, and thus TStringList, provides a SaveToFile method you use to save the content of the string list to a file. Each string in the list is written to a separate line in the file.
Many VCL controls, like TMemo, use a string list (TStrings) internally to manipulate text in a memo control on a line-by-line basis.
TStringList.SaveToFile - Extra "Empty" Line !?When using the SaveToFile method of the string list, the resulting TXT file, when opened in Notepad, will have an extra empty line added to the end of the file.
Here's the code:
The result of the above action, when you open "c:\one.txt" in Notepad, will look like:
sl : TStringList;
sl := TStringList.Create;
sl.Add('this is the only added line');
Note that there are actually two lines in the file, while only the first line of text ("this is the only added line") was added in the code above using the Add method.
this is the only added line
Now, in 99.99% cases and situations you would say "I do not care about the extra empty line"!
I did so also until I had a situation where another application was reading my files created using TStringList.SaveToFile. The reader (other vendor) refused the files as there was an extra line not expected to be in the file that must have had only 1 line.
The sLineBreak constantThe sLineBreak constant defined in the System unit, on Windows, equals to "#13#10". "#13#10" stands for carriage return (#13) + line feed (#10).
When you open the above file in a hex viewer you will see it ending in "0D 0A". 0D is the hex representation of 13 and 0A is 10.
TStringList appends a new line (#$0D#$0A) to the file, if your text does not already end in a new line.
Remove #13#10 Added By TStringList.SaveToFileIf you are working with the TStringList to process lines of text, and you need to save those lines as a txt file, *without* and empty line added to the end of the file, you should remove it before saving the file:
The problem is solved using the TFileStream class.var sl : TStringList; fs : TFileStream; begin sl := TStringList.Create; fs := TFileStream.Create('c:\two.txt', fmCreate); try sl.Add('this is the only added line'); sl.SaveToStream(fs, sl.Encoding); //constant System.sLineBreak = #13#10 on Windows fs.Size := fs.Size - Length(System.sLineBreak); finally sl.Free; fs.Free; end; end;
- You add the lines of text to your string list as you did previously.
- Before saving the text to a file we need to remove that added empty line from the string list (that would get added if we are to use SaveToFile).
- Save the string list content to the file stream
- Remove the two last "characters". We set the Size property of the TFileStream for this by reducing it by the length of the sLineBreak constant.
- Save the file using TFileStream saving mechanism
Can this be more easy?Including the TFileStream to the above code and doing some magic looks like "too much to do".
Starting with Delphi 2010, the RTL includes the "ioutils.pas" unit hosting dozens of file and folder related functions grouped into TFile, TDirectory, TPath and alike classes (records to be more precise).
The TFile record exposes a handy method "AppendAllText(const Path, Contents: string);". The AppendAllText appends a given text "Contents" to a file. If the file specified by the Path parameter exists, the text is appended to it; otherwise, the file is created and filled with the given text.
With the AppendAllText, my code now looks as:
And that's it :)
if TFile.Exists('c:\three.txt') then TFile.Delete('c:\three.txt);
TFile.AppendAllText('c:\three.txt, 'only one line of text', TEncoding.ASCII);
I hate it when problems tend to raise from out of nowhere.