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

  • 相关阅读:
    201521044091《Java程序设计》第7周学习总结
    201521044091《java程序设计》第四次总结
    201521044091 《java程序设计》第八周学习总结
    201521044091 《Java程序设计》第5周学习总结
    201521044091 《Java程序设计》第2周学习总结
    201521044091 《Java程序设计》第3周学习总结
    MySQL设置字符集CHARACTER SET
    Create My MySQL configuration by Percona
    How to use jQuery to manipulate Cookies
    How to use OpenXml to import xml data to Sql server
  • 原文地址:https://www.cnblogs.com/zhangjun1130/p/1892661.html
Copyright © 2011-2022 走看看