【问题标题】:XmlException while deserializing xml file in UTF-16 encoding format以 UTF-16 编码格式反序列化 xml 文件时出现 XmlException
【发布时间】:2014-08-14 00:38:22
【问题描述】:

使用 C# 的 XmlSerializer。

在反序列化给定文件夹中的所有 xml 文件的过程中,我看到 XmlException "There is an error in XML document (0, 0)". 和 InnerException 是 "There is no Unicode byte order mark. Cannot switch to Unicode".

目录中的所有 xml 都是“UTF-16”编码的。唯一的区别是,一些 xml 文件缺少在反序列化时我正在使用其对象的类中定义的元素。

例如,假设我的文件夹中有 3 种不同类型的 xml:

file1.xml

<?xml version="1.0" encoding="utf-16"?>
<ns0:PaymentStatus xmlns:ns0="http://my.PaymentStatus">
</ns0:PaymentStatus>

file2.xml

<?xml version="1.0" encoding="utf-16"?>
<ns0:PaymentStatus xmlns:ns0="http://my.PaymentStatus">
<PaymentStatus2 RowNum="1" FeedID="38" />
</ns0:PaymentStatus>

file3.xml

<?xml version="1.0" encoding="utf-16"?>
<ns0:PaymentStatus xmlns:ns0="http://my.PaymentStatus">
<PaymentStatus2 RowNum="1" FeedID="38" />
<PaymentStatus2 RowNum="2" FeedID="39" Amt="26.0000" />
</ns0:PaymentStatus>

我有一个类来表示上面的xml:

[XmlTypeAttribute(AnonymousType = true, Namespace = "http://my.PaymentStatus")]
[XmlRootAttribute("PaymentStatus", Namespace = "http://http://my.PaymentStatus", IsNullable = true)]
public class PaymentStatus
{

    private PaymentStatus2[] PaymentStatus2Field;

    [XmlElementAttribute("PaymentStatus2", Namespace = "")]
    public PaymentStatus2[] PaymentStatus2 { get; set; }

    public PaymentStatus()
    {
        PaymentStatus2Field = null;
    }
}

[XmlTypeAttribute(AnonymousType = true)]
[XmlRootAttribute(Namespace = "", IsNullable = true)]

public class PaymentStatus2
{

    private byte rowNumField;
    private byte feedIDField;
    private decimal AmtField;
    public PaymentStatus2()
    {
        rowNumField = 0;
        feedIDField = 0;
        AmtField = 0.0M;
    }

    [XmlAttributeAttribute()]
    public byte RowNum { get; set; }

    [XmlAttributeAttribute()]
    public byte FeedID { get; set; }
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public decimal Amt { get; set; }
}

按照 sn-p 为我进行反序列化:

foreach (string f in filePaths)
{
  XmlSerializer xsw = new XmlSerializer(typeof(PaymentStatus));
  FileStream fs = new FileStream(f, FileMode.Open);
  PaymentStatus config = (PaymentStatus)xsw.Deserialize(new XmlTextReader(fs));
}

我错过了什么吗?它必须与编码格式有关,因为当我尝试用 UTF-8 手动替换 UTF-16 时,它似乎工作得很好。

【问题讨论】:

    标签: c# xml encoding xmlserializer xmlexception


    【解决方案1】:

    我今天在使用第三方网络服务时遇到了同样的错误。

    我遵循 Alexei 的建议,使用 StreamReader 并设置编码。之后,可以在 XmlTextReader 构造函数中使用 StreamReader。这是使用原始问题中的代码的实现:

    foreach (string f in filePaths)
    {
      XmlSerializer xsw = new XmlSerializer(typeof(PaymentStatus));
      FileStream fs = new FileStream(f, FileMode.Open);
      StreamReader stream = new StreamReader(fs, Encoding.UTF8);
      PaymentStatus config = (PaymentStatus)xsw.Deserialize(new XmlTextReader(stream));
    }
    

    【讨论】:

      【解决方案2】:

      encoding="utf-16" 很可能与存储的 XML 编码无关,因此导致解析器无法将流作为 UTF-16 文本读取。

      由于您有评论,将“编码”参数更改为“utf-8”可以让您阅读文本,我假设文件实际上是 UTF8。您可以通过在您选择的编辑器(即 Visual Studio)中将文件打开为二进制文件而不是文本来轻松验证这一点。

      出现这种不匹配的最可能原因是将 XML 保存为 writer.Write(document.OuterXml)(首先获取字符串表示形式,其中放置“utf-16”,但默认情况下使用 utf-8 编码将字符串写入流)。

      可能的解决方法 - 以与编写代码对称的方式读取 XML - 读取为字符串,而不是从字符串加载 XML。

      正确修复 - 确保正确存储 XML。

      【讨论】:

        【解决方案3】:

        我不知道这是否是最好的方法,但如果我的输入流不包含 BOM,我只是使用 XDocument 来处理不同的编码......例如:

        public static T DeserializeFromString<T>(String xml) where T : class
            {
                try
                {
                    var xDoc = XDocument.Parse(xml);
                    using (var xmlReader = xDoc.Root.CreateReader())
                    {
                        return new XmlSerializer(typeof(T)).Deserialize(xmlReader) as T;
                    }
                }
                catch ()
                {
                    return default(T);
                }
            }
        

        当然,您可能想抛出任何异常,但对于我复制的代码,我不需要知道它是否失败或为什么失败......所以我只是吃掉了异常。

        【讨论】:

          猜你喜欢
          • 2013-10-17
          • 2013-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-16
          • 1970-01-01
          • 2017-06-18
          • 1970-01-01
          相关资源
          最近更新 更多