Delphi - TStringList Save/Load to stream encoding

RepeatUntil picture RepeatUntil · Jun 22, 2016 · Viewed 8.5k times · Source

I'm working with TStringList with TMemeorySteam a lot in my project.

  msTmp := TMemoryStream.Create;
  try
     lTemp.SaveToStream(msTmp, TEncoding.Unicode);
  finally
    msTmp.Free;
  end;
  .....
  lTemp := TStringList.Create;
  try
     lTemp.LoadFromFile(msTmp, TEncoding.Unicode);
  finally
    lTemp.Free;
  end;

How i can tell the LoadFromStream() and SaveToStream() that the stream is UTF-16 encoded by default in my project without including the encoded type in each call. so i can call LoadFromStream(msTmp) only and it will load with UTF-16 encoded.

Answer

Remy Lebeau picture Remy Lebeau · Jun 22, 2016

Have a look at the TStrings.DefaultEncoding property.

The default encoding for the current object.

DefaultEncoding is used when the nil encoding is specified in a call to LoadFromStream or SaveToStream.

By default, DefaultEncoding is set to Default. The user can change DefaultEncoding if another default encoding is desired for LoadFromStream or SaveToStream.

However, watch out for the TStrings.Encoding property:

Character encoding determined during reading from a stream or file.

Encoding is a read-only property that contains the value of the character encoding detected when the LoadFromStream or LoadFromFile methods are called. If a file or stream does not contain a BOM (the encoding value cannot be detected) then Encoding is set to the value specified in the DefaultEncoding property.

Encoding is used in the SaveToStream and SaveToFile methods.

If the Encoding parameter [of LoadFromStream] is not given, then the strings are loaded using the appropriate encoding. The value of the encoding is obtained by calling the GetBufferEncoding routine of the TEncoding class. LoadFromStream then saves the value of the encoding in the Encoding property, to be used if the stream is saved.

So, as long as you do not call LoadFrom...(), you can set DefaultEncoding to TEncoding.Unicode and then call SaveTo...() without specifying a value for the Encoding parameter.

But, once you call LoadFrom...(), the Encoding property takes priority over the DefaultEncoding property for subsequent calls to SaveTo...(). As long as the files are not BOM'ed, the Encoding property will match the DefaultEncoding property. But if a non-UTF16LE BOM is encountered, all bets are off.

To ensure TEncoding.Unicode is always used, you should continue using the Encoding parameter of LoadFrom...() and SaveTo...(), that is why they exist. They take first priority, the (Default)Encoding properties are fallbacks when input/output encodings are not explicitly stated.