If you save it to a .txt
file, you lose the ability to re-load it correctly, since you don't know if a give line break was originally embedded in a string, or separates two strings.
If you save it to another textual format, like .ini
, you can escape/unescape the line breaks as needed, eg:
function Encode(const S: String): String;
begin
Result := StringReplace(S, '<', '<<', [rfReplaceAll]);
Result := StringReplace(Result, #13#10, '<CRLF>', [rfReplaceAll]);
Result := StringReplace(Result, #13, '<CR>', [rfReplaceAll]);
Result := StringReplace(Result, #10, '<LF>', [rfReplaceAll]);
end;
Ini := TIniFile.Create(...);
try
Ini.WriteInteger('section', 'count', MyStringList.Count);
for I := 0 to MyStringList.Count-1 do
Ini.WriteString('section', IntToStr(I), Encode(MyStringList[I]);
finally
Ini.Free;
end;
function Decode(const S: String): String;
begin
Result := StringReplace(S, '<LF>', #10, [rfReplaceAll]);
Result := StringReplace(Result, '<CR>', #13, [rfReplaceAll]);
Result := StringReplace(Result, '<CRLF>', #13#10, [rfReplaceAll]);
Result := StringReplace(Result, '<<', '<', [rfReplaceAll]);
end;
Ini := TIniFile.Create(...);
try
Count := Ini.ReadInteger('section', 'count', 0);
for I := 0 to Count-1 do
MyStringList.Add(Decode(Ini.ReadString('section', IntToStr(I), ''));
finally
Ini.Free;
end;
If you save it to a binary format, you can preserve the line breaks as-is, eg:
procedure WriteIntegerToStream(Stream: TStream; Value: Integer);
begin
Stream.WriteBuffer(Value, SizeOf(Integer));
end;
procedure WriteStringToStream(Stream: TStream; const Value: String);
var
U: UTF8String;
Count: Integer;
begin
U := UTF8String(Value); // or UTF8Encode(Value) prior to D2009
Count := Length(U);
WriteIntegerToStream(Stream, Count);
if Count > 0 then
Stream.WriteBuffer(PAnsiChar(U)^, Count * SizeOf(AnsiChar));
end;
Strm := TFileStream.Create(..., fmCreate);
try
WriteIntegerToStream(Stream, MyStringList.Count);
for I := 0 to MyStringList.Count-1 do
WriteStringToStream(Stream, MyStringList[I]);
finally
Stream.Free;
end;
function ReadIntegerFromStream(Stream: TStream): Integer;
begin
Stream.ReadBuffer(Result, SizeOf(Integer));
end;
function ReadStringFromStream(Stream: TStream): String;
var
Count: Integer;
U: UTF8String;
begin
Count := ReadIntegerFromStream(Stream);
if Count > 0 then
begin
SetLength(U, Count);
Stream.ReadBuffer(PAnsiChar(U)^, Count * SizeOf(AnsiChar));
Result := String(U); // or UTF8Decode(U) prior to D2009
end else
Result := '';
end;
Stream := TFileStream.Create(..., fmOpenRead or fmShareDenyWrite);
try
Count := ReadIntegerFromStream(Stream);
for I := 0 to Count-1 do
MyStringList.Add(ReadStringFromStream(Stream));
finally
Stream.Free;
end;
MyStringList[0]
is a single line string.<li>
does not cause a line break;<li>Test1</li>
in a single line is totally valid HTML. If you write it with line breaks to a file, it will be read back as separate lines. If you've stored<li>
line break` Test1line break
</li>`, then it's not a single line string. – Ken White