XmlSerializer.Serialize BOM отсутствует - PullRequest
2 голосов
/ 04 июля 2019

Я использую этот код для хранения моего класса:

FileStream stream = new FileStream(myPath, FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(myClass));
serializer.Serialize(stream, myClass);
stream.Close();

Это записывает файл, который я могу читать с XmlSerializer.Deserialize. Однако созданный файл не является правильным текстовым файлом. XmlSerializer.Serialize не хранит спецификацию, но все еще вставляет многобайтовые символы. Таким образом, он неявно объявляется файлом ANSI (поскольку мы ожидаем, что файл XML будет текстовым, а в Windows текстовый файл без спецификации рассматривается как ANSI), показывая в некоторых редакторах ö как Ã.

Это известная ошибка? Или какие-то настройки, которые мне не хватает?

Вот с чего начинается сгенерированный файл:

<?xml version="1.0"?>
<SvnProjects xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

Первый байт в файле - это шестнадцатеричный 3C, т. Е. <.

Ответы [ 2 ]

4 голосов
/ 04 июля 2019

Наличие или отсутствие спецификации не является определением «правильного текстового файла». На самом деле, я бы сказал, что наиболее типичным форматом в наши дни является UTF-8 без спецификации; Я не думаю, что я когда-либо видел, что кто-то действительно использует спецификацию UTF-8 в реальных системах! Но: если вам нужна спецификация, это нормально: просто введите правильный Encoding в; если вы хотите UTF-8 с спецификацией:

using (var writer = XmlWriter.Create(myPath, s_settings))
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    serializer.Serialize(writer, obj);
}

с:

static readonly XmlWriterSettings s_settings =
    new XmlWriterSettings { Encoding = new UTF8Encoding(true) };

В результате получается файл, который запускает EF-BB-BF, спецификацию UTF-8.

Если вам нужна кодировка , отличающаяся от , просто замените new UTF8Encoding на то, что вам нужно, не забывая включить спецификацию.

(примечание: статический экземпляр Encoding.UTF8 имеет включенную спецификацию, но IMO лучше быть очень явным, если вы намерены использовать спецификацию, точно так же, как вы должны четко указывать, какую Encoding вы намеревались использовать)


Редактировать: ключевое отличие здесь в том, что Serialize(Stream, object) заканчивается использованием:

XmlTextWriter xmlWriter = new XmlTextWriter(stream, encoding: null) {
    Formatting = Formatting.Indented,
    Indentation = 2
};

, который затем заканчивается использованием:

public StreamWriter(Stream stream) : this(stream,
    encoding: UTF8NoBOM, // <==== THIS IS THE PROBLEM
    bufferSize: 1024, leaveOpen: false)
{
}

итак: UTF-8 без спецификации используется по умолчанию, если вы используете этот API.

1 голос
/ 04 июля 2019
  1. вы должны xml экземпляр не определение класса
  2. для получения Unicode вы должны объявить XmlWriter или TextWriter
FileStream stream = new FileStream(myPath, FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(myClass));
XmlWriter writer = new XmlTextWriter(fs, Encoding.Unicode);
serializer.Serialize(writer, myClass);
stream.Close();
...