c#从文件序列化数据契约
本文关键字:数据 契约 序列化 文件 | 更新日期: 2023-09-27 18:11:08
我有一个记录到文件中的Xml消息列表,特别是DataContract消息。我正试着逐个从文件中反序列化它们。我不想一次将整个文件读入内存,因为我认为它非常大。
我有这个序列化的实现,它可以工作。为此,我使用FileStream进行序列化,读取字节并使用正则表达式确定元素的结束。然后获取元素并使用DataContractSerializer来获得实际的对象。
但是我被告知我应该使用更高级别的代码来完成这个任务,似乎这应该是可能的。我有下面的代码,我认为应该工作,但它没有。
FileStream readStream = File.OpenRead(filename);
DataContractSerializer ds = new DataContractSerializer(typeof(MessageType));
MessageType msg;
while ((msg = (MessageType)ds.ReadObject(readStream)) != null)
{
Console.WriteLine("Test " + msg.Property1);
}
上面的代码由一个包含以下内容的输入文件提供:
<MessageType>....</MessageType>
<MessageType>....</MessageType>
<MessageType>....</MessageType>
似乎我可以正确读取和反序列化第一个元素,但之后它失败了,说:
System.Runtime.Serialization.SerializationException was unhandled
Message=There was an error deserializing the object of type MessageType. The data at the root level is invalid. Line 1, position 1.
Source=System.Runtime.Serialization
我在某个地方读到,这是由于DataContractSerializer的工作方式与填充''0' s结束-但我无法弄清楚如何解决这个问题时,从流中读取没有弄清楚MessageType标签的结束以其他方式。是否有另一个序列化类,我应该使用?或者是解决这个问题的方法?
谢谢!
在对文件中的数据进行反序列化时,WCF默认使用只能使用适当XML文档的读取器。你正在阅读的文档不是——它包含多个根元素,所以它实际上是一个片段。您可以通过使用ReadObject
的另一个重载(如下面的示例所示)将序列化器正在使用的读取器更改为接受片段的读取器(通过使用XmlReaderSettings
对象)。或者您可以在<MessageType>
元素周围有某种形式的换行元素,并且您将读取直到阅读器位于包装器的结束元素处。
public class StackOverflow_7760551
{
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
public override string ToString()
{
return string.Format("Person[Name={0},Age={1}]", this.Name, this.Age);
}
}
public static void Test()
{
const string fileName = "test.xml";
using (FileStream fs = File.Create(fileName))
{
Person[] people = new Person[]
{
new Person { Name = "John", Age = 33 },
new Person { Name = "Jane", Age = 28 },
new Person { Name = "Jack", Age = 23 }
};
foreach (Person p in people)
{
XmlWriterSettings ws = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
OmitXmlDeclaration = true,
Encoding = new UTF8Encoding(false),
CloseOutput = false,
};
using (XmlWriter w = XmlWriter.Create(fs, ws))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
dcs.WriteObject(w, p);
}
}
}
Console.WriteLine(File.ReadAllText(fileName));
using (FileStream fs = File.OpenRead(fileName))
{
XmlReaderSettings rs = new XmlReaderSettings
{
ConformanceLevel = ConformanceLevel.Fragment,
};
XmlReader r = XmlReader.Create(fs, rs);
while (!r.EOF)
{
Person p = new DataContractSerializer(typeof(Person)).ReadObject(r) as Person;
Console.WriteLine(p);
}
}
File.Delete(fileName);
}
}
也许您的文件包含BOM对于UTF-8编码
XmlSerializer xml = new XmlSerializer(typeof(MessageType));
XmlDocument xdoc = new XmlDocument();
xdoc.Load(stream);
foreach(XmlElement elm in xdoc.GetElementsByTagName("MessageType"))
{
MessageType mt = (MessageType)xml.Deserialize(new StringReader(elm.OuterXml));
}