首页 > 代码库 > 序列化与反序列化 - BinaryFormatter二进制(.dat)、SoapFormatter(.soap)、XmlSerializer(.xml)

序列化与反序列化 - BinaryFormatter二进制(.dat)、SoapFormatter(.soap)、XmlSerializer(.xml)

  序列化的作用是什么?为什么要序列化?

  1、在进程下次启动时读取上次保存的对象的信息。

  2、在不同的应用程序域或进程之间传递数据。

  3、在分布式应用程序中的各应用程序之间传输对象。

  所为序列化,就是将对象先转换为一种适当格式,然后再将其传输到目标位置的过程。

  所为适当格式,有时候需要是二进制格式,有时候需要SOAP格式或者其他的XML,JSON格式等,也可以使应用程序所特有的、定制化的格式。因此,可以将序列化视为将对象的状态保存到流或缓冲区的方法,和序列化相反的就是烦序列化,就是把对象或数据从序列化的状态恢复为其原始状态的过程。

  .Net提供三种预定义的格式化程序:

  1、BinaryFormatter

  2、SoapFormatter

  3、XmlSerializer

  下面来分别介绍各种序列化。

BinaryFormatter

  BinaryFormatter类允许使用二进制格式将对象序列化与反序列化,它位于System.Runtime.Serialization.Formatters.Binary命名空间。

  当使用BinaryFormatter类序列化这种方式时,除了明确标注为不参与序列化的成员,一个对象中所有可以序列化的成员,包括当前对象引用的其他对象,都可以序列化。结果就是所有相关对象都会被复制一份新的拷贝。而不是简单地复制引用。

public class Program
    {
        string strFile = @"D:\person.dat";
        static void Main(string[] args)
        {
            ArrayList favourites = new ArrayList();
            favourites.Add("看电视");
            favourites.Add("看电影");
            favourites.Add("上网冲浪");

            Person person = new Person(favourites) { height = "175cm", birthday = "2000-1-1" };
            person.SetWeight(80.00);
            Console.WriteLine(person.ToString());

            Program Ser = new Program();
            Ser.Serialize(person);

            //从文件中反序列化
            Person person2 = Ser.DeSerialize();
            Console.WriteLine(person2.ToString());

            Console.ReadKey();
        }

        [Serializable]  //注意此处要标记为可序列化,否则报错
        public class Person
        {
            //私有字段
            private string name = "张三";
            private ArrayList favourites = new ArrayList();
            private double weight;

            //公共字段
            public string height;

            //公共属性,但加了NonSerialized特性
            [NonSerialized]
            public string birthday;

            //默认构造函数
            public Person()
            { }

            public Person(ArrayList favourites)
            {
                this.favourites = favourites;
            }

            //只读属性
            public string Name
            {
                get { return name; }
            }

            //只读集合属性
            public ArrayList Favourites
            {
                get { return favourites; }
            }

            //方法
            public void SetWeight(double weight)
            {
                this.weight = weight;
            }

            public override string ToString()
            {
                StringBuilder builder = new StringBuilder();
                builder.Append("Name:" + Name + "\n");
                builder.Append("Height:" + height + "\n");
                builder.Append("Birthday:" + birthday + "\n");
                builder.Append("Weight:" + weight + "\n");
                builder.Append("Favourites:");
                for (int i = 0; i < favourites.Count; i++)
                {
                    builder.Append(favourites[i] + "\n");
                }
                return builder.ToString();
            }
        }

        //序列化
        public void Serialize(Person person)
        {
            using (FileStream fs = new FileStream(strFile, FileMode.Create))
            { 
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(fs,person);
            }
        }

        //反序列化
        public Person DeSerialize()
        {
            Person person;
            using (FileStream fs = new FileStream(strFile, FileMode.Open))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                person = formatter.Deserialize(fs) as Person;
            }
            return person;
        }
    }

  输出结果如下所示:

  

  注意观察到,除了birthday使用了属性[NonSerialized]没有被序列化之外,其他的值无论是公共的还是私有的,也不管是否只读,全部都被序列化了。

 SoapFormatter

   SoapFormatter类型允许把对象持久化为一个SOAP信息,当希望使用HTTP协议远程发送对象时,这是一个不错的方式。SoapFormatter位于System.Runtime.Serialization.Formatters.Soap命名空间。它将对象序列化为一个本地文件person.soap。

public class Program
    {
        string strFile = @"D:\person.soap";
        static void Main(string[] args)
        {
            ArrayList favourites = new ArrayList();
            favourites.Add("看电视");
            favourites.Add("看电影");
            favourites.Add("上网冲浪");

            Person person = new Person(favourites) { height = "175cm", birthday = "2000-1-1" };
            person.SetWeight(80.00);
            Console.WriteLine(person.ToString());

            Program Ser = new Program();
            Ser.Serialize(person);

            //从文件中反序列化
            Person person2 = Ser.DeSerialize();
            Console.WriteLine(person2.ToString());

            Console.ReadKey();
        }

        [Serializable]  //注意此处要标记为可序列化,否则报错
        public class Person
        {
            //私有字段
            private string name = "张三";
            private ArrayList favourites = new ArrayList();
            private double weight;

            //公共字段
            public string height;

            //公共属性,但加了NonSerialized特性
            [NonSerialized]
            public string birthday;

            //默认构造函数
            public Person()
            { }

            public Person(ArrayList favourites)
            {
                this.favourites = favourites;
            }

            //只读属性
            public string Name
            {
                get { return name; }
            }

            //只读集合属性
            public ArrayList Favourites
            {
                get { return favourites; }
            }

            //方法
            public void SetWeight(double weight)
            {
                this.weight = weight;
            }

            public override string ToString()
            {
                StringBuilder builder = new StringBuilder();
                builder.Append("Name:" + Name + "\n");
                builder.Append("Height:" + height + "\n");
                builder.Append("Birthday:" + birthday + "\n");
                builder.Append("Weight:" + weight + "\n");
                builder.Append("Favourites:");
                for (int i = 0; i < favourites.Count; i++)
                {
                    builder.Append(favourites[i] + "\n");
                }
                return builder.ToString();
            }
        }

        //序列化
        public void Serialize(Person person)
        {
            using (FileStream fs = new FileStream(strFile, FileMode.Create))
            {
                SoapFormatter formatter = new SoapFormatter();
                formatter.Serialize(fs,person);
            }
        }

        //反序列化
        public Person DeSerialize()
        {
            Person person;
            using (FileStream fs = new FileStream(strFile, FileMode.Open))
            {
                SoapFormatter formatter = new SoapFormatter();
                person = formatter.Deserialize(fs) as Person;
            }
            return person;
        }
    }

  注意到上面的代码与BinaryFormatter几乎一模一样,只是改了一下类名,而保存文件的扩展名。输出结果如下所示:

  

  生成的.soap文件代码如下所示:

<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:Program_x002B_Person id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/ConsoleApplication1/ConsoleApplication1%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<name id="ref-3">张三</name>
<favourites href="#ref-4"/>
<weight>80</weight>
<height id="ref-5">175cm</height>
</a1:Program_x002B_Person>
<a2:ArrayList id="ref-4" xmlns:a2="http://schemas.microsoft.com/clr/ns/System.Collections">
<_items href="#ref-6"/>
<_size>3</_size>
<_version>3</_version>
</a2:ArrayList>
<SOAP-ENC:Array id="ref-6" SOAP-ENC:arrayType="xsd:anyType[4]">
<item id="ref-7" xsi:type="SOAP-ENC:string">看电视</item>
<item id="ref-8" xsi:type="SOAP-ENC:string">看电影</item>
<item id="ref-9" xsi:type="SOAP-ENC:string">上网冲浪</item>
</SOAP-ENC:Array>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>