【问题标题】:Unable to deserialize multiple objects using XML Serializer, getting InvalidOperationException无法使用 XML Serializer 反序列化多个对象,出现 InvalidOperationException
【发布时间】:2013-08-30 05:52:01
【问题描述】:

我有一个简单的 Cust 类,我想使用 XML 序列化对其进行序列化。

public class Cust

{
public string CustName;
public int ID;
public Cust() { }
public Cust(string nm, int id)
{
CustName = nm;
ID = id;
}
public string DisInfo()
{
return CustName+" "+ID;
}

}

我的序列化函数是:

private void button1_Click(object sender, EventArgs e)

{
//Serialize
FileStream fs = new FileStream(@"C:\tmp\cust.xml", FileMode.Create);
XmlSerializer xs = new XmlSerializer(typeof(Cust));
Cust c1 = new Cust("Rahul S",111);
Cust c2 = new Cust("John D", 222);

xs.Serialize(fs, c1);
xs.Serialize(fs, c2);
fs.Close();
}

输出是cust.xml

<?xml version="1.0"?>
<Cust xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <CustName>Rahul S</CustName>
  <ID>111</ID>
</Cust><?xml version="1.0"?>
<Cust xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <CustName>John D</CustName>
  <ID>222</ID>
</Cust>

然后我尝试反序列化;从 xml 文件中取回 Cust 对象

private void button2_Click(object sender, EventArgs e)

{

//Deserialize

FileStream fs = new FileStream(@"C:\tmp\cust.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
XmlSerializer xs = new XmlSerializer(typeof(Cust));

Cust c1 = (Cust)xs.Deserialize(fs);//Exception
Cust c2 = (Cust)xs.Deserialize(fs);

fs.Close();

}

这会引发异常

InvalidOperationException Unhandled- XML 文档中的错误 (5,10)

我知道如果我将多个对象放在一个集合中,我可以存储它们。

但在这种情况下,我将无法将列表附加到 xml 文件中。我想逐个序列化多个对象;然后我想反序列化它们。

【问题讨论】:

  • Xml 可以有一个根节点。将您的对象包装在一个对象中(或使用它们的数组)
  • 是的,我知道所有对象都可以放入数组并存储在 xml 中。但是那我将如何附加它呢?意思是如果我以后想添加更多对象,我该怎么做?
  • 没有这样的东西。您将读取 xml 并写回新的。 Xml 不是数据库。
  • 但是在正常的序列化中,比如二进制序列化,我们可以在现有文件中添加更多对象并全部读取。 XML序列化不可能吗???

标签: c# .net xml-serialization xmlserializer xml-deserialization


【解决方案1】:

使用对象数组

//Serialize
FileStream fs = new FileStream(@"C:\tmp\cust.xml", FileMode.Create);
XmlSerializer xs = new XmlSerializer(typeof(Cust[]));
Cust c1 = new Cust("Rahul S",111);
Cust c2 = new Cust("John D", 222);

xs.Serialize(fs, new[]{c1,c2});
fs.Close();

//Deserialize

FileStream fs = new FileStream(@"C:\tmp\cust.xml", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
XmlSerializer xs = new XmlSerializer(typeof(Cust[]));

Cust[] c1 = (Cust[])xs.Deserialize(fs);//Exception

fs.Close();

【讨论】:

  • 如果我想添加更多客户对象,以后如何在 XML 中附加信息
  • 您可以使用 XML 属性来获得所需的效果。 XmlElement、XmlArray、XmlAttribute、XmlRoot 等...
  • 你能告诉我怎么做吗?我想将对象保存在 XML 而不是集合中。并在以后使用反序列化检索它们。
  • 试试XmlSerializer xs = new XmlSerializer(typeof(Cust[]),new XmlRootAttribute("Customers"));
【解决方案2】:

诀窍是(以某种方式)将每个 XML 与另一个分开。

  1. 使用XmlWriter 将对象序列化为文件(紧凑格式,无制表符/新行)
  2. 在文件中添加新行(在序列化消息之后)
  3. 对所有对象重复
  4. 使用StreamReader.ReadLine逐行读取文件,每一行代表一个完整的XML文档
  5. 为您刚刚读取的每一行创建一个内存流,并从中反序列化您的对象

【讨论】:

    猜你喜欢
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多