Я пытаюсь прочитать какой-то XML, полученный от внешнего интерфейса через сокет.Проблема в том, что в XML-заголовке указана неправильная кодировка (там написано iso-8859-1, но это utf-16BE).Документально подтверждено, что кодировкой является utf-16BE, но, очевидно, они забыли установить правильную кодировку.
Чтобы игнорировать кодировку при десериализации, я использую StringReader, например:
private static T DeserializeXmlData<T>(byte[] xmlData)
{
var xmlString = Encoding.BigEndianUnicode.GetString(xmlData);
using (var reader = new StringReader(xmlString))
{
reader.ReadLine(); // Eat header line
using (var xmlReader = XmlReader.Create(reader))
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(xmlReader);
}
}
}
Вышеприведенное на самом деле работает нормально, но мне не нравится та часть, где я просто пропускаю строку заголовка, вызывая ReadLine.Есть ли менее хрупкий способ обойти кодировку, указанную в XML-заголовке?
Решение с StreamReader
Используя StreamReader, я могу переопределить кодировку, указанную вXML-заголовок.Указание XmlReaderSettings.IgnoreProcessingInstructions или нет ничего не изменило.Интересно, что StreamReader игнорирует указанную кодировку, если находит юникодную метку порядка байтов.
Напомним:
- Если XmlReader инициализируется с помощью TextReader, кодировка XML-заголовка игнорируется.
- Если используется StringReader, XmlReader завершается ошибкой, если существует метка порядка байтов в Юникоде.
- Если используется StreamReader, метка порядка байтов в Юникоде переопределяет кодировку StreamReader.
- XmlReaderSettings.IgnoreProcessingInstructions = true не имеет значения при использовании TextReader.
В заключение, наиболее надежное решение, похоже, использует StreamReader, так как использует порядок байтовОтметить, если имеется.
private static T DeserializeXmlData<T>(byte[] xmlData)
{
using (var xmlDataStream = new MemoryStream(xmlData))
{
using (var reader = new StreamReader(xmlDataStream, Encoding.BigEndianUnicode))
{
using (var xmlReader = XmlReader.Create(reader))
{
var serializer = new XmlSerializer(typeof (T));
return (T) serializer.Deserialize(xmlReader);
}
}
}
}