Как я могу сохранить объект из класса TStringList в файл (Delphi XE 2) с UTF8 без спецификации?

Когда я сохраняю объект из содержимого файла класса TStringList в файл, файл сохраняется с UTF-8 правильно, но по умолчанию UTF-8 со спецификацией.

Мой код:

myFile := TStringList.Create;
try
  myFile.Text := myData;
  myFile.saveToFile('myfile.dat', TEncoding.UTF8)
finally
  FreeAndNil(myFile);
end;

В примере файл «myfile.dat» отображается в кодировке «UTF-8 BOM».

Как я могу сохранить файл без спецификации?


person Fabiano Silva    schedule 28.08.2015    source источник


Ответы (2)


Вам просто нужно установить для свойства TStrings.WriteBOM значение false.

Документация говорит нам об этом:

Заставит SaveToStream или SaveToFile записать спецификацию.

Установите для параметра WriteBOM значение True, чтобы SaveToStream записывала спецификацию (метку порядка байтов) в поток и чтобы SaveToFile записывала спецификацию в файл.

person Sir Rufo    schedule 29.08.2015
comment
Спасибо @sir-rufo, это действительно хороший выход. Но верно с новым файлом. Не верно, когда читает файл перед сохранением (LoadFromFile...). Возможно проблемы с Delphi XE2. Я постараюсь обновить версию Delphi. Это так странно. - person Fabiano Silva; 29.08.2015
comment
Я не понял сути, потому что не видел ни одной строки кода (XE8), где установлено свойство WriteBOM, за исключением constructor и AssignTo, что, как и ожидалось. Значение по умолчанию — true, и оно не изменится, пока вы этого не сделаете. - person Sir Rufo; 30.08.2015
comment
Для справки, TStrings.WriteBOM был добавлен в Delphi XE, но TStrings впервые получил поддержку TEncoding в D2009. Но SirRufo прав, WriteBOM всегда будет True, даже после загрузки, если вы явно не установите для него значение False. Методы TStrings.LoadFrom...() не изменяют значение WriteBOM, но они изменяют значение свойства TStrings.Encoding. - person Remy Lebeau; 02.09.2015

Вы можете добиться этого, создав свой собственный класс кодирования, унаследованный от TUTF8Encoding, и переопределив метод GetPreamble:

type
  TUTF8EncodingNoBOM = class(TUTF8Encoding)
  public
    function GetPreamble: TBytes; override;
  end;

function TUTF8EncodingNoBOM.GetPreamble: TBytes; begin SetLength(Result, 0); end;

person Andy_D    schedule 28.08.2015
comment
Andy_D В моем тесте использовался модифицированный вами класс, конечный файл сохранен в кодировке ANSI. - person Fabiano Silva; 28.08.2015
comment
@FabianoSilva Ты уверен? Как вы проверяли кодировку вывода? - person GabrielF; 28.08.2015
comment
Да @GabrielF, в Notepad++ выходная кодировка — ANSI. - person Fabiano Silva; 28.08.2015
comment
@FabianoSilva IIRC, по умолчанию, если файл не содержит символов, отличных от ANSI, notepad++ идентифицирует его как ANSI (в данном случае UTF8 и ANSI — одно и то же). Попробуйте добавить некоторые специальные символы перед сохранением или изменить конфигурацию Notepad ++, чтобы идентифицировать ее как UTF8 без спецификации (я не помню, где вы это изменили). - person GabrielF; 28.08.2015
comment
@FabianoSilva Думаю, меньше Setttings -> Preferences -> New document. Если вы выберете Encoding вместо UTF8 w/o BOM и отметите Apply to opened ANSI files, Notepad++ будет идентифицировать как простые файлы ASCII UTF8. - person GabrielF; 28.08.2015
comment
@GabrielF, Блокнот++ меня обманул. Закрытие и повторное открытие файла заставило показать правильную кодировку. Спасибо. - person Fabiano Silva; 31.08.2015