首页 > 代码库 > 序列化与反序列化 - 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>