完全被这个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]属性,这样才能工作
您的两个方法都有一个基本但很容易修复的错误。
在方法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对象,看看它是什么样子,然后将其作为起点。