繁体   English   中英

C#从文件序列化数据合同

[英]C# Serializing datacontracts from file

我有一个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到结尾的方式而引起的-但我无法弄清楚如何从流中读取时解决此问题而不弄清楚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)); 
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM