Проблема сериализации XmlTextWriter

Я пытаюсь создать кусок xml. Я создал dataclasses с xsd.exe. Корневой класс MESSAGE.

Итак, создав MESSAGE и заполнив все его свойства, я сериализую его так:

serializer = new XmlSerializer(typeof(Xsd.MESSAGE));
StringWriter sw = new StringWriter();
serializer.Serialize(sw, response);
string xml = sw.ToString();

До сих пор все идет хорошо, строка xml содержит допустимый (UTF-16 закодированный) xml. Теперь мне нравится создавать xml с кодировкой UTF-8, поэтому я делаю это вот так:

Изменить: забыл включить объявление потока

serializer = new XmlSerializer(typeof(Xsd.MESSAGE));
using (MemoryStream stream = new MemoryStream())
{
    XmlTextWriter xtw = new XmlTextWriter(stream, Encoding.UTF8);
    serializer.Serialize(xtw, response);
    string xml = Encoding.UTF8.GetString(stream.ToArray());
}

И здесь возникает проблема: используя этот подход, строка xml добавляется с недопустимым char (печально известный квадрат).
Когда я проверяю char следующим образом:

char c = xml[0];

Я вижу, что c имеет значение 65279.
Кто-нибудь знает, откуда это происходит?
Я могу легко решить это, отключив первый char:

xml = xml.SubString(1);

Но я предпочел бы знать, что происходит, чем слепо разрезать первый char.

Кто-нибудь может пролить свет на это? Спасибо!

Ответы

Ответ 1

Здесь ваш код изменен, чтобы не добавлять байтовый порядок (спецификация):

var serializer = new XmlSerializer(typeof(Xsd.MESSAGE));
Encoding utf8EncodingWithNoByteOrderMark = new UTF8Encoding(false);
XmlTextWriter xtw = new XmlTextWriter(stream, utf8EncodingWithNoByteOrderMark);
serializer.Serialize(xtw, response);
string xml = Encoding.UTF8.GetString(stream.ToArray());

Ответ 2

65279 - это знак порядка байтов в Юникоде - вы уверены, что получаете 65249? Предполагая, что это действительно спецификация, вы можете избавиться от нее, создав экземпляр UTF8Encoding, который не использует спецификацию. (Подробности см. В конструкциях.)

Однако есть более простой способ получить UTF-8. Вы можете использовать StringWriter, но производный класс, который переопределяет свойство Encoding. См. этот ответ для примера.