zoukankan      html  css  js  c++  java
  • .net中对象序列化技术浅谈(ZZ)

    序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。反之,反序列化根据流重新构造对象。此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件中“恢复”对象到序列化之前的状态。
    在.net中有提供了几种序列化的方式:
    二进制序列化
    XML序列化
    SOAP序列化

    二进制序列化
    所谓二进制序列化,指的是对象序列化之后是二进制形式的。二进制序列化是通过BinaryFormatter类来实现的,这个类位于System.Runtime.Serialization.Formatters.Binary命名空间下。

    XML序列化
    所谓XML序列化,是指对象序列化之后的结果是XML形式的。保存XML序列化是通过XmlSerializer 类来实现的, 这个类位于System.Xml.Serialization命名空间下。

    SOAP序列化
    所谓SOAP序列化是指对象序列化之后的结果符合SOAP协议,也就是可以通过SOAP协议传输(不知道SOAP协议?百度一下吧)。SOAP序列化是通过SoapFormatter类来实现的,这个类位于System.Runtime.Serialization.Formatters.Soap命名空间下,并且需要注意需要手动添加对这个命名空间的引用,如下图所示:
     

    下面编写一个类用于序列化和反序列化,这个类的代码如下:

    using System;  
    using System.Collections.Generic;  
    using System.Text;  
     
    namespace MySerializeDemo  
    {  
        [Serializable]  
        /// <summary>  
        /// 要序列化的对象  
        /// 作者:周公  
        /// 编写时间:2009-03-10  
        /// </summary>  
        public class MyObject  
        {  
            //[NonSerialized]  
            private string name;  
            private DateTime birthday;  
            private string homePlace;  
            /// <summary>  
            /// 出生地  
            /// </summary>  
            public string HomePlace  
            {  
                get { return homePlace; }  
                set { homePlace = value; }  
            }  
       
            /// <summary>  
            /// 生日  
            /// </summary>  
            public DateTime Birthday  
            {  
                get { return birthday; }  
                set { birthday = value; }  
            }  
       
            /// <summary>  
            /// 姓名  
            /// </summary>  
            public string Name  
            {  
                get { return name; }  
                set { name = value; }  
            }  
       
            /// <summary>  
            /// 年龄  
            /// </summary>  
            public int Age  
            {  
                get { return DateTime.Now.Year - birthday.Year; }  
            }  
            /// <summary>  
            /// override了ToString()方法  
            /// </summary>  
            /// <returns></returns>  
            public override string ToString()  
            {  
                return string.Format("姓名:{0},生日:{1},出生地:{2},年龄:{3}",name,birthday,homePlace,Age);  
            }  
       
        }  

    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace MySerializeDemo
    {
        [Serializable]
        /// <summary>
        /// 要序列化的对象
        /// 作者:周公
        /// 编写时间:2009-03-10
        /// </summary>
        public class MyObject
        {
            //[NonSerialized]
            private string name;
            private DateTime birthday;
            private string homePlace;
            /// <summary>
            /// 出生地
            /// </summary>
            public string HomePlace
            {
                get { return homePlace; }
                set { homePlace = value; }
            }
     
            /// <summary>
            /// 生日
            /// </summary>
            public DateTime Birthday
            {
                get { return birthday; }
                set { birthday = value; }
            }
     
            /// <summary>
            /// 姓名
            /// </summary>
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
     
            /// <summary>
            /// 年龄
            /// </summary>
            public int Age
            {
                get { return DateTime.Now.Year - birthday.Year; }
            }
            /// <summary>
            /// override了ToString()方法
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                return string.Format("姓名:{0},生日:{1},出生地:{2},年龄:{3}",name,birthday,homePlace,Age);
            }
     
        }
    }
    下面是分别用上面的三个类进行序列化和反序列化的代码:

    view plaincopy to clipboardprint?
    using System;  
    using System.Collections.Generic;  
    using System.Text;  
    using System.IO;  
    using System.Runtime.Serialization.Formatters;  
    using System.Runtime.Serialization.Formatters.Binary;  
    using System.Runtime.Serialization.Formatters.Soap;  
    using System.Xml.Serialization;  
     
    namespace MySerializeDemo  
    {  
        class Program  
        {  
            static void Main(string[] args)  
            {  
                MyObject obj = new MyObject();  
                obj.Birthday = new DateTime(1979, 11, 7);  
                obj.HomePlace = "湖北";  
                obj.Name = "周公";  
                Console.WriteLine("========使用BinaryFormatter类进行序列化和反序列化。====");  
                BinarySerialize(obj);  
                BinaryDeserialize("C:\\MyObject.dat");  
                Console.WriteLine("========使用SoapFormatter类进行序列化和反序列化。====");  
                SOAPSerialize(obj);  
                SOAPDeserialize("C:\\MyObject.soap");  
                Console.WriteLine("========使用XmlSerializer类进行序列化和反序列化。====");  
                XMLSerialize(obj);  
                XMLDeserialize("C:\\MyObject.xml");  
            }  
            /// <summary>  
            /// 二进制序列化对象  
            /// </summary>  
            /// <param name="obj"></param>  
            public static void BinarySerialize(MyObject obj)  
            {  
                using (FileStream stream = new FileStream("C:\\MyObject.dat", FileMode.Create, FileAccess.Write))  
                {  
                    BinaryFormatter formater = new BinaryFormatter();  
                    formater.Serialize(stream, obj);  
                    Console.WriteLine("对象已经被序列化。" + obj.ToString());  
                }  
            }  
            /// <summary>  
            /// 二进制反序列化  
            /// </summary>  
            /// <param name="fileName"></param>  
            public static void BinaryDeserialize(string fileName)  
            {  
                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))  
                {  
                    BinaryFormatter formater = new BinaryFormatter();  
                    MyObject obj=(MyObject)formater.Deserialize(stream);  
                    Console.WriteLine("对象已经被反序列化。" + obj.ToString());  
                }  
            }  
     
            /// <summary>  
            /// 二进制序列化对象  
            /// </summary>  
            /// <param name="obj"></param>  
            public static void SOAPSerialize(MyObject obj)  
            {  
                using (FileStream stream = new FileStream("C:\\MyObject.soap", FileMode.Create, FileAccess.Write))  
                {  
                    SoapFormatter formater = new SoapFormatter();  
                    formater.Serialize(stream, obj);  
                    Console.WriteLine("对象已经被序列化。" + obj.ToString());  
                }  
            }  
            /// <summary>  
            /// 二进制反序列化  
            /// </summary>  
            /// <param name="fileName"></param>  
            public static void SOAPDeserialize(string fileName)  
            {  
                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))  
                {  
                    SoapFormatter formater = new SoapFormatter();  
                    MyObject obj = (MyObject)formater.Deserialize(stream);  
                    Console.WriteLine("对象已经被反序列化。" + obj.ToString());  
                }  
            }  
            /// <summary>  
            /// XML序列化  
            /// </summary>  
            /// <param name="obj"></param>  
            public static void XMLSerialize(MyObject obj)  
            {  
                using (FileStream stream = new FileStream("C:\\MyObject.xml", FileMode.Create, FileAccess.Write))  
                {  
                    XmlSerializer serializer = new XmlSerializer(typeof(MyObject));  
                    serializer.Serialize(stream, obj);  
                    Console.WriteLine("对象已经被序列化。" + obj.ToString());  
                }  
            }  
            /// <summary>  
            /// XML反序列化  
            /// </summary>  
            /// <param name="fileName"></param>  
            public static void XMLDeserialize(string fileName)  
            {  
                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))  
                {  
                    XmlSerializer serializer = new XmlSerializer(typeof(MyObject));  
                    MyObject obj = (MyObject)serializer.Deserialize(stream);  
                    Console.WriteLine("对象已经被反序列化。" + obj.ToString());  
                }  
            }  
        }  

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Runtime.Serialization.Formatters;
    using System.Runtime.Serialization.Formatters.Binary;
    using System.Runtime.Serialization.Formatters.Soap;
    using System.Xml.Serialization;

    namespace MySerializeDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                MyObject obj = new MyObject();
                obj.Birthday = new DateTime(1979, 11, 7);
                obj.HomePlace = "湖北";
                obj.Name = "周公";
                Console.WriteLine("========使用BinaryFormatter类进行序列化和反序列化。====");
                BinarySerialize(obj);
                BinaryDeserialize("C:\\MyObject.dat");
                Console.WriteLine("========使用SoapFormatter类进行序列化和反序列化。====");
                SOAPSerialize(obj);
                SOAPDeserialize("C:\\MyObject.soap");
                Console.WriteLine("========使用XmlSerializer类进行序列化和反序列化。====");
                XMLSerialize(obj);
                XMLDeserialize("C:\\MyObject.xml");
            }
            /// <summary>
            /// 二进制序列化对象
            /// </summary>
            /// <param name="obj"></param>
            public static void BinarySerialize(MyObject obj)
            {
                using (FileStream stream = new FileStream("C:\\MyObject.dat", FileMode.Create, FileAccess.Write))
                {
                    BinaryFormatter formater = new BinaryFormatter();
                    formater.Serialize(stream, obj);
                    Console.WriteLine("对象已经被序列化。" + obj.ToString());
                }
            }
            /// <summary>
            /// 二进制反序列化
            /// </summary>
            /// <param name="fileName"></param>
            public static void BinaryDeserialize(string fileName)
            {
                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    BinaryFormatter formater = new BinaryFormatter();
                    MyObject obj=(MyObject)formater.Deserialize(stream);
                    Console.WriteLine("对象已经被反序列化。" + obj.ToString());
                }
            }

            /// <summary>
            /// 二进制序列化对象
            /// </summary>
            /// <param name="obj"></param>
            public static void SOAPSerialize(MyObject obj)
            {
                using (FileStream stream = new FileStream("C:\\MyObject.soap", FileMode.Create, FileAccess.Write))
                {
                    SoapFormatter formater = new SoapFormatter();
                    formater.Serialize(stream, obj);
                    Console.WriteLine("对象已经被序列化。" + obj.ToString());
                }
            }
            /// <summary>
            /// 二进制反序列化
            /// </summary>
            /// <param name="fileName"></param>
            public static void SOAPDeserialize(string fileName)
            {
                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    SoapFormatter formater = new SoapFormatter();
                    MyObject obj = (MyObject)formater.Deserialize(stream);
                    Console.WriteLine("对象已经被反序列化。" + obj.ToString());
                }
            }
            /// <summary>
            /// XML序列化
            /// </summary>
            /// <param name="obj"></param>
            public static void XMLSerialize(MyObject obj)
            {
                using (FileStream stream = new FileStream("C:\\MyObject.xml", FileMode.Create, FileAccess.Write))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
                    serializer.Serialize(stream, obj);
                    Console.WriteLine("对象已经被序列化。" + obj.ToString());
                }
            }
            /// <summary>
            /// XML反序列化
            /// </summary>
            /// <param name="fileName"></param>
            public static void XMLDeserialize(string fileName)
            {
                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
                    MyObject obj = (MyObject)serializer.Deserialize(stream);
                    Console.WriteLine("对象已经被反序列化。" + obj.ToString());
                }
            }
        }
    }
    这个程序的运行效果如下:
     
    可见通过上面三个类都能实现将对象序列化保存,并且都能反序列化还原到对象被序列化之前的状态(这正是序列化意义所在,能保存对象运行时的状态并且还能还原)。如果运行上面的代码会在C盘根目录下创建三个文件,分别是MyObject.dat、MyObject.soap和MyObject.xml文件,因为MyObject.dat是二进制文件,所以无法查看文件的内容,但是我们可以打开MyObject.soap和MyObject.xml这两个文件来比较一下有什么区别。
    MyObject.soap文件的后缀虽然是.soap,但是还是可以用记事本打开的,下面是MyObject.soap文件的内容:
    view plaincopy to clipboardprint?
    <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
    <SOAP-ENV:Body> 
    <a1:MyObject id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo,%20Version=1.0.0.0,%20Culture=neutral,%20PublicKeyToken=null"> 
    <name id="ref-3">周公</name> 
    <birthday>1979-11-07T00:00:00.0000000+08:00</birthday> 
    <homePlace id="ref-4">湖北</homePlace> 
    </a1:MyObject> 
    </SOAP-ENV:Body> 
    </SOAP-ENV:Envelope> 
    <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
    <a1:MyObject id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/MySerializeDemo/MySerializeDemo,%20Version=1.0.0.0,%20Culture=neutral,%20PublicKeyToken=null">
    <name id="ref-3">周公</name>
    <birthday>1979-11-07T00:00:00.0000000+08:00</birthday>
    <homePlace id="ref-4">湖北</homePlace>
    </a1:MyObject>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    MyObject.xml文件也可以用记事本打开,它的内容如下:

    view plaincopy to clipboardprint?
    <?xml version="1.0"?> 
    <MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
      <HomePlace>湖北</HomePlace> 
      <Birthday>1979-11-07T00:00:00</Birthday> 
      <Name>周公</Name> 
    </MyObject> 
    <?xml version="1.0"?>
    <MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <HomePlace>湖北</HomePlace>
      <Birthday>1979-11-07T00:00:00</Birthday>
      <Name>周公</Name>
    </MyObject>
    熟悉SOAP协议的朋友一看MyObject.soap文件的内容就知道它符合SOAP协议,MyObject.xml文件毫无疑问是一个符合XML规范的文件。

    对代码作几点说明:
    1、如果采用BinaryFormatter类或者SoapFormatter类来实现序列化,则一定要给类加上Serializable属性,如代码中所示:
    view plaincopy to clipboardprint?
    [Serializable]  
        /// <summary>  
        /// 要序列化的对象  
        /// 作者:周公  
        /// 编写时间:2009-03-10  
        /// </summary>  
        public class MyObject 
    [Serializable]
        /// <summary>
        /// 要序列化的对象
        /// 作者:周公
        /// 编写时间:2009-03-10
        /// </summary>
        public class MyObject
    如果不给要序列化的对象加上这个属性,那么采用采用BinaryFormatter类或者SoapFormatter类来实现序列化时会报异常,但使用XmlSerializer 类序列化对象时可以不用这个属性。
    2、另外,如果不想序列化某个字段,可以给其加上NonSerialized属性,这样在序列化时就不会保存这个这个字段的值了,比如不想序列化name这个字段,可以如下写代码:

    view plaincopy to clipboardprint?
    …//其它代码  
    //[NonSerialized]  
    private string name;  
    …//其它代码 
    …//其它代码
    //[NonSerialized]
    private string name;
    …//其它代码
    再次运行刚才的程序会得到如下效果:
     
    看有黄色底线部分,因为name字段不被序列化,所以通过二进制序列化和SOAP序列化之后再反序化就得不到原来的值了。
    3、最后还需要说明一点的是,SoapFormatter类在.net3.5开始已经过时了,微软建议使用BinaryFormatter类来序列化和反序列化了。

    周公
    2009-03-11 0:17

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zhoufoxcn/archive/2009/03/11/3978874.aspx

  • 相关阅读:
    关于高等数学的学习笔记(一)(未完)
    第十七章 波粒二象性笔记
    网课摸鱼一时爽,提交笔记火葬场——网课物理笔记
    讲丶数学
    啥是快速幂
    2019年十一月(CSP S游记及AFO)
    luogu P3959(2017noipTG D2T2
    圆锥曲线:椭圆大题解题报告
    圆锥曲线:椭圆小题解题报告
    sql查询json格式中的内容
  • 原文地址:https://www.cnblogs.com/zhangjun1130/p/1892661.html
Copyright © 2011-2022 走看看