C # serializing datacontracts from file

I have a list of Xml messages, namely DataContract messages that I write to a file. And I'm trying to deserialize them from a file one by one. I do not want to read the entire file in memory immediately, because I expect it to be very large.

I have an implementation of this serialization and it works. I did this by serializing using a FileStream and reading bytes and using a regular expression to determine the end of the element. Then, taking the element and using the DataContractSerializer, you will get the actual object.

But I was told that I should use a higher level code to complete this task, and it seems that it should be possible. I have the following code, which I think should work, but it is not.

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); } 

In the above code, an input file is supplied containing something in the following lines:

 <MessageType>....</MessageType> <MessageType>....</MessageType> <MessageType>....</MessageType> 

It looks like I can read and deserialize the first element correctly, but after that it doesn't say:

 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 

I read somewhere that this is due to the way the DataContractSerializer works with the augmented "\ 0" to the end - but I could not figure out how to fix this problem when reading from a stream without figuring out the end of the MessageType tag in another way. Is there another Serialization class that I should use? or perhaps a way to solve this problem?

Thanks!

+4
source share
3 answers

When you deserialize data from a file, WCF uses a reader by default, which can only consume proper XML documents. The document you are reading is missing - it contains several root elements, so it effectively fragmentes. You can change the reader that uses the serializer using another ReadObject overload, as shown in the example below, to the one that receives the fragments (using the XmlReaderSettings object). Or you can have some kind of wrapper element around the <MessageType> elements, and you would read until the reader was placed at the end of the wrapper element.

 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); } } 
+1
source

Your file may contain a specification. It is common for encoding UTF-8.

0
source
 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)); } 
0
source

All Articles