• C#序列化和反序列化


     

     从网上摘来的文章,大家共勉!

     

    首先,什么是序列化与反序列化呢?

    序列化就是将对象的状态信息转换为可以存储或传输形式的过程。其实就是将对象持久化,比如说把对象保存为二进制或者是XML的方式。可以将对象序列到流、磁盘、内存和网络等等。相反,反序列化则是将存储或传输形式转换为对象的过程。

     

    那么,运用序列化的好处又是什么呢?

    1)以某种存储形式(二进制或者是XML等)使对象持久化。序列化和反序列化用来保存内存中的数据,它不是C#中独有的技术,比如win7的休眠就是该技术的应用,在C#程序中可以用来保存对象,和对象当前状态,下次打开时通过反序列化获得,一般用在服务器启动(反序列化)和关闭(序列化)时保存数据。

    2)使对象的传递更加容易,比如你用ajax向服务器请求信息,服务器可以直接将model对象通过序列化来输出json字符串,也可以通过反序列化将你传过去的json字符串组装成对象,就免去了拼字符串和解析字符串的过程。

     

    最后,.Net里面怎么实现序列化技术?

    1)二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。

    2) XML 序列化仅序列化公共属性和字段,且不保持类型保真度。当您要提供或使用数据而不限制使用该数据的应用程序时,这一点是很有用的。由于 XML 是一个开放式标准,因此,对于通过 Web 共享数据而言,这是一个很好的选择。SOAP 同样是一个开放式标准,这使它也成为一个颇具吸引力的选择。----------以上内容摘自百科的内容与百度的内容.

     

    关于这两点的概念,我自己也不大明白是什么意思?

    保持类型保真度,一开始我是认为是成员变量的类型,以为用XML序列化的话,都会变成是string的类型,但是发现根本不是这样。成员变量的类型都能保存,那这里说的类型保真类到底是指什么?XML序列化仅序列化公共属性和字段,但是我用私有字段,发现也一样可以序列化。我是定义一个私有字段,然后通过公共属性来给它赋值,然后在反序列化里面通过公共属性来取私有字段的内容,发现是可以的,不知道是不是我的理解有什么问题?

     

    1#针对二进制序列化与反序列化,.Net是使用BinaryFormatter对象来进行序列化与反序列化。

    一般的实现方法,是把可序列化的类用特征类[Serializable]来标志,当然,不想序列类的成员,可以用[NonSerialized]特征类来标志。类里面的所有成员变量都能被序列化。然后实例化命名空间System.Runtime.Serialization.Formatters.Binary下的BinaryFormatter对象,借助其Serialize方法来实现序列化与Deserialize方法来实现反序列化。

    using System;

    using System.IO;

    using System.Collections;

    using System.Runtime.Serialization.Formatters.Binary;

    using System.Runtime.Serialization;

     

    [Serializable]

    public class SerializeObject

    {

        public int ID

        {

            get;

            set;

        }

     

        public string UserName

        {

            get;

            set;

        }

     

        public string Password

        {

            get;

            set;

        }

     

        [NonSerialized]

        public string notSerialize;

    }

     

    public class App

    {

        [STAThread]

        static void Main()

        {

            Serialize();

            Deserialize();

        }

     

        static void Serialize()

        {

            SerializeObject serializeObject = new SerializeObject();

            serializeObject.ID = 1;

            serializeObject.UserName = "csdbfans";

            serializeObject.Password = "csdbfans";

            serializeObject.notSerialize = "博客园";

     

            FileStream fs = new FileStream("DataFile.dat", FileMode.Create);

     

            BinaryFormatter formatter = new BinaryFormatter();

            try

            {

                formatter.Serialize(fs, serializeObject);

            }

            catch (SerializationException e)

            {

                Console.WriteLine("Failed to serialize. Reason: " + e.Message);

                throw;

            }

            finally

            {

                fs.Close();

            }

        }

     

     

        static void Deserialize()

        {

            SerializeObject serializeObject = null;

     

            FileStream fs = new FileStream("DataFile.dat", FileMode.Open);

            try

            {

                BinaryFormatter formatter = new BinaryFormatter();

     

                serializeObject = (SerializeObject)formatter.Deserialize(fs);

            }

            catch (SerializationException e)

            {

                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);

                throw;

            }

            finally

            {

                fs.Close();

            }

     

            Console.WriteLine("反序列Serializable的结果:ID->" + serializeObject.ID + ", UserName->"

                               + serializeObject.UserName + ", Password->" + serializeObject.Password);

            Console.WriteLine("反序列化NonSerialized结果:" + serializeObject.notSerialize);

        }

    }

    结果为:

    其实你如果进到DataFile.dat文件的话,你会发现用记事本,写字板来打开的话,都是会出现乱码。因为它是用二进制的方式来保存的,所以你只有是在用二进制的方式下才能看到里面的内容。不过对于我们来说,即使看到二进制的内容,我们也不大可能知道是什么意思。所以可能只有通过反序列化的方式来读出文档的内容。

     

    2#针对XML序列化与反序列化,.Net提供了两种方式来实现。

    其一:使用XmlSerializer类将对象序列化到XML文档中和从XML文档反序列化出对象。

    与第1点的区别,摘自寒江笠博文

    I)不使用[Serializable]特征类与[NonSerializable]特征类,只使用特征类[System.Xml.Serialization.XmlIgnoreAttribute来标志哪些成员变量不需要被序列化。

    II)不能序列化私有成员变量(不确定,因为我试过可以

    类只能是public 

    III)要求被序列化的类要有一个默认的构造函数(不确定,不知道这里的构造函数是为了什么而需要的

    using System;

    using System.IO;

    using System.Collections;

    using System.Xml.Serialization;

    using System.Runtime.Serialization;

     

    public class SerializeObject

    {

     

        public int ID

        {

            get;

            set;

        }

     

        public string UserName

        {

            get;

            set;

        }

     

        public string Password

        {

            get;

            set;

        }

     

        [XmlIgnoreAttribute]

        public string notSerialize;

    }

     

    public class App

    {

        [STAThread]

        static void Main()

        {

            Serialize();

            Deserialize();

        }

     

        static void Serialize()

        {

            SerializeObject serializeObject = new SerializeObject();

            serializeObject.ID = 1;

            serializeObject.UserName = "csdbfans";

            serializeObject.Password = "csdbfans";

            serializeObject.notSerialize = "博客园";

     

            FileStream fs = new FileStream("DataFile.xml", FileMode.Create);

            XmlSerializer formatter = new XmlSerializer(typeof(SerializeObject));

            try

            {

                formatter.Serialize(fs, serializeObject);

            }

            catch (SerializationException e)

            {

                Console.WriteLine("Failed to serialize. Reason: " + e.Message);

                throw;

            }

            finally

            {

                fs.Close();

            }

        }

     

     

        static void Deserialize()

        {

            SerializeObject serializeObject = null;

     

            FileStream fs = new FileStream("DataFile.xml", FileMode.Open);

            try

            {

                XmlSerializer formatter = new XmlSerializer(typeof(SerializeObject));

                serializeObject = (SerializeObject)formatter.Deserialize(fs);

            }

            catch (SerializationException e)

            {

                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);

                throw;

            }

            finally

            {

                fs.Close();

            }

     

            Console.WriteLine("反序列Serializable的结果:ID->" + serializeObject.ID + ", UserName->" 

                              + serializeObject.UserName + ", Password->" + serializeObject.Password);        Console.WriteLine("反序列化NonSerialized结果:" + serializeObject.notSerialize);    }}

    结果:

     

    其二:使用SoapFormatter类将对象序列化到XML文档中和从XML文档反序列化出对象。

    同样是序列化到XML文档里面,只不过序列化里面包含了SOAP特有的额外信息。

    SoapFormatter 和 BinaryFormatter 两个类实现 IRemotingFormatter 接口以支持远程过程调用 (RPC),实现 IFormatter 接口(由 IRemotingFormatter 继承)以支持对象图形的序列化。SoapFormatter 类还支持对 ISoapMessage 对象进行 RPC,而不必使用 IRemotingFormatter 功能。此概念来自MSDN文档,有兴趣请点击去研读详细内容。

    其二的方法跟第一点(1#)的实现方法基本一样,毕竟都是实现相同的接口,有一定的共性,只是最终存储的格式或者是传输的方式不一样。

     

    using System;

    using System.IO;

    using System.Collections;

    using System.Runtime.Serialization;

    using System.Runtime.Serialization.Formatters.Soap;

     

    [Serializable]

    public class SerializeObject

    {

        public int ID

        {

            get;

            set;

        }

     

        public string UserName

        {

            get;

            set;

        }

     

        public string Password

        {

            get;

            set;

        }

     

        [NonSerialized]

        public string notSerialize;

    }

     

    public class App

    {

        [STAThread]

        static void Main()

        {

            Serialize();

            Deserialize();

        }

     

        static void Serialize()

        {

            SerializeObject serializeObject = new SerializeObject();

            serializeObject.ID = 1;

            serializeObject.UserName = "csdbfans";

            serializeObject.Password = "csdbfans";

            serializeObject.notSerialize = "博客园";

     

            FileStream fs = new FileStream("DataFile.soap", FileMode.Create);

     

            SoapFormatter formatter = new SoapFormatter();

            try

            {

                formatter.Serialize(fs, serializeObject);

            }

            catch (SerializationException e)

            {

                Console.WriteLine("Failed to serialize. Reason: " + e.Message);

                throw;

            }

            finally

            {

                fs.Close();

            }

        }

     

     

        static void Deserialize()

        {

            SerializeObject serializeObject = null;

     

            FileStream fs = new FileStream("DataFile.soap", FileMode.Open);

            try

            {

                SoapFormatter formatter = new SoapFormatter();

     

                serializeObject = (SerializeObject)formatter.Deserialize(fs);

            }

            catch (SerializationException e)

            {

                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);

                throw;

            }

            finally

            {

                fs.Close();

            }

     

            Console.WriteLine("反序列Serializable的结果:ID->" + serializeObject.ID + ", UserName->"

                               + serializeObject.UserName + ", Password->" + serializeObject.Password);

            Console.WriteLine("反序列化NonSerialized结果:" + serializeObject.notSerialize);

        }

    }

    结果为:

    <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:SerializeObject id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/assem/MyTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"><_x003C_ID_x003E_k__BackingField>1</_x003C_ID_x003E_k__BackingField><_x003C_UserName_x003E_k__BackingField id="ref-3">csdbfans</_x003C_UserName_x003E_k__BackingField><_x003C_Password_x003E_k__BackingField href="#ref-3"/></a1:SerializeObject></SOAP-ENV:Body>

    </SOAP-ENV:Envelope>

     

    这里使用寒江笠博文来进行两种技术的对比:

    二进制序列化的优点:

    1)所有的类成员变量(包括只读的)都可以被序列化;

    2)性能非常好。

    XML序列化的优点:

    1)互操作性好;

    2)不需要严格的二进制依赖;

    3)可读性强。

     

  • 相关阅读:
    FeignClient服务之间调用,数据传输超过10M
    docker安装streamset
    Nginx 相关命令
    Maven构建命令相关
    ubuntu18.04的安装与学习记录
    Java8获取世界标准时
    我所遇到的正则表达式使用场景
    linux查看磁盘命令du df
    db2获取第一条数据
    Linux命令 dos2unix 的实际应用场景
  • 原文地址:https://www.cnblogs.com/xinyebs/p/3139354.html
Copyright © 2020-2023  润新知