我正在尝试通过套接字读取从外部接口接收的一些 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 找到一个 unicode 字节顺序标记,它会忽略指定的编码。
回顾一下:
- 如果使用 TextReader 初始化 XmlReader,则忽略 XML 标头编码。
- 如果使用 StringReader,如果存在 unicode 字节顺序标记,则 XmlReader 将失败。
- 如果使用 StreamReader,则 unicode 字节顺序标记会覆盖 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);
}
}
}
}