完全被这个XML反序列化卡住了

本文关键字:反序列化 XML | 更新日期: 2023-09-27 18:23:42

我一辈子都无法弄清楚为什么我无法将XML反序列化为类实例。请参阅下面我尝试过的两种方法(以及它们各自的错误消息)。

方法一:

    public static SkillCollection Deserialize(string path)
    {
        using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(Path.Combine(path, "Skills.xml"))))
        {
            SkillCollection skills = null;
            try
            {
                var serializer = new DataContractSerializer(typeof(SkillCollection));
                var reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null);
                skills = (SkillCollection)serializer.ReadObject(memoryStream);
            }
            catch (SerializationException ex)
            {
                Globals.Instance.ApplicationLogger.Log("The object graph could not be deserialized from the binary stream because of the following error: " + ex);
            }
            return skills;
        }
    }

这样调用:Skills = SkillCollection.Deserialize(path);

错误:XmlException was thrown: UnexpectedEndOfFile


方法二:

    public static object Deserialize(string xml, Type toType)
    {
        Console.WriteLine("File exists? " + File.Exists(xml));
        using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
        {
            XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.UTF8, new XmlDictionaryReaderQuotas(), null);
            DataContractSerializer serializer = new DataContractSerializer(toType);
            return serializer.ReadObject(reader);
        }
    }

这样调用:Skills = (SkillCollection) SkillCollection.Deserialize(Path.Combine(path, "Skills.xml"), typeof(SkillCollection));

错误1:XmlException was thrown: "The data at the root level is invalid. Line 1, position 1."

错误2:SerializationException was thrown: "There was an error deserializing the object of type MagBot_FFXIV.SkillCollection. The data at the root level is invalid. Line 1, position 1."


我的XML:

<Skills>
  <Fire>
    <Cast>0.00</Cast>
    <ReCast>60.00</ReCast>
    <MPCost>0</MPCost>
    <Button>0</Button>
  </Fire>
  <Ice>
    <Cast>2.49</Cast>
    <ReCast>2.49</ReCast>
    <MPCost>9</MPCost>
    <Button>1</Button>
  </Ice>
</Skills>

非常感谢你的帮助。


更新:

我以前曾使用LINQ2XML,但它对我的情况没有帮助。请看我今天早些时候写的这篇文章:XML到字典到自定义类的实例


我的最终代码如下。效果很好,希望它能帮助其他人

    public static object DataContractSerializer_Deserialize(string path, Type toType)
    {
        using (var sr = new FileStream(path, FileMode.Open))
        {
            SkillCollection p = null;
            var serializer = new DataContractSerializer(toType);
            var reader = XmlDictionaryReader.CreateTextReader(sr, new XmlDictionaryReaderQuotas());
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        if (serializer.IsStartObject(reader))
                        {
                            Console.WriteLine(@"Found the element");
                            p = (SkillCollection)serializer.ReadObject(reader);
                        }
                        Console.WriteLine(reader.Name);
                        break;
                }
            }
            return p;
        }
    }

注意:

  • 请记住,您的XML元素必须按字母顺序排列,DataContractSerializer才能工作(这不适用于XmlSerializer)
  • 此外,您必须在SkillCollection和SkillCollection类的上方包含具有Name和Namespace的[DataContract]属性,这样才能工作

完全被这个XML反序列化卡住了

您的两个方法都有一个基本但很容易修复的错误。

在方法1中,行:

new MemoryStream(Encoding.UTF8.GetBytes(Path.Combine(path, "Skills.xml")))

是错误的,因为内存流接收文件的PATH的字节表示,而不是它的实际内容。

在方法2中,我猜它也有同样的错误,但参数名称"xml"具有误导性。但是,由于您首先使用xml检查文件是否存在,我认为这也意味着文件的PATH,而不是其内容。

试试这个:

new MemoryStream(Encoding.UTF8.GetBytes(File.ReadAllText(Path.Combine(path, "Skills.xml"))))

假设DataContractSerializer的实际文件内容格式正确,则应该有效。如果没有,我建议您首先序列化一个活动的SkillsCollection对象,看看它是什么样子,然后将其作为起点。

相关文章: