C#序列化與反序列化詳解

什么是序列化以及如何實現(xiàn)序列化?
序列化是通過將對象轉(zhuǎn)換為字節(jié)流,從而存儲對象或?qū)ο髠鬏數(shù)絻?nèi)存,數(shù)據(jù)庫或文件的過程。主要用途是保存對象的狀態(tài),包括對象的數(shù)據(jù),以便能夠在需要是重建對象。反向過程稱為 反序列化。

如上圖所示,對象 object 被序列化為 流,其中不僅包含數(shù)據(jù)、還包含對象類型的相關(guān)信息,如版本、區(qū)域性和程序集名稱。然后可以將此流中的內(nèi)容存儲到數(shù)據(jù)庫、文件或內(nèi)存中。
序列化的用途:
通過序列化,可以執(zhí)行如下操作:通過 Web 服務(wù)將對象發(fā)送到遠程應(yīng)用程序、在域之間傳遞對象、以 XML 字符串的形式傳遞對象通過防火墻、跨應(yīng)用程序維護安全性或用戶專屬信息。
讓對象可序列化:
需要具有對象、包含已序列化對象的一個流,以及一個 Fromatter。
System.Runtime.Serialization 包含序列化和反序列化對象所必須的類。
將 SerializableAttribute 特性應(yīng)用于某個類型,以表示此類型的實例可以被序列化,如果對沒有 SerializableAttribute 特性的類型進行序列化,則會引發(fā)異常。
如果想讓類中的某個字段不可序列化,可以使用 NonSerializedAttribute 特性。
序列化的三種類型--二進制、XML、JSON
可以使用二進制 binary 或 XML 進行序列化,在 二進制序列化中,所有內(nèi)容都會被序列化,且性能也很好,使用二進制編碼來生成精簡的序列化,可以用于基于存儲或socket的網(wǎng)絡(luò)流。
XML 序列化可提高可讀性,以及對象共享和使用的靈活性,XML 序列化將對象的公共字段和屬性或方法的參數(shù)和返回值序列化成符合特定 XML 格式的流,
System.Xml.Serialization 包含序列化和反序列化 XML 所需要的類
如果要保存運行程序過程的數(shù)據(jù)要么保存到數(shù)據(jù)庫中,要么新建一個普通的文件,然后把數(shù)據(jù)保存進去.但是這兩者有個缺點就是,不能把原有數(shù)據(jù)的結(jié)構(gòu)也保存進去.比如一個類中的字段值保存進去后再讀取出來必須再解析下才行.序列化技術(shù)讓你省去了解析的過程.保存后再讀取時直接得到一個class
序列化的方式有三種:BinaryFormatter,SoapFormatter,XmlSerializer
1.BinaryFormatter
保存成二進制數(shù)據(jù)流.用法示例:
using System.IO;using System.Runtime.Serialization.Formatters.Binary;[]//如果要想保存某個class中的字段,必須在class前面加個這樣attribute(C#里面用中括號括起來的標志符)public class Person{public int age;public string name;[] //如果某個字段不想被保存,則加個這樣的標志public string secret;}
序列化:
classProgram{staticvoid Main(string[] args){Person person = newPerson();person.age = 18;person.name = "tom";person.secret = "i will not tell you";FileStream stream =newFileStream(@"c:\temp\person.dat",FileMode.Create);BinaryFormatter bFormat =newBinaryFormatter();bFormat.Serialize(stream, person);stream.Close();}
反序列化:
classProgram{staticvoid Main(string[] args){Person person = newPerson();FileStream stream =newFileStream(@"c:\temp\person.dat",FileMode.Open);BinaryFormatter bFormat =newBinaryFormatter();person = (Person)bFormat.Deserialize(stream);//反序列化得到的是一個object對象.必須做下類型轉(zhuǎn)換stream.Close();Console.WriteLine(person.age + person.name + person.secret);//結(jié)果為18tom.因為secret沒有有被序列化.}
2.SoapFormatter
把數(shù)據(jù)保存成xml文件.里面除了保存的內(nèi)容還有些額外的Soap信息.它的用法和BinaryFormatter一樣.只要把BinaryFormatter都替換成SoapFormatter就行.
把文件名改為person.xml
另外就是添加名稱空間:using System.Runtime.Serialization.Formatters.Soap;
這個名稱空調(diào)對就的程序集有時VS沒有自動引用.你必須手動去引用.選中project,右擊選擇Add Reference.在.NET的標簽下選擇
System.Runtime.Serialization.Formatters.Soap.然后點OK.
補充:SOAP(Simple Object Access Protocol )簡單對象訪問協(xié)議是在分散或分布式的環(huán)境中交換信息的簡單的協(xié)議,是一個基于XML的協(xié)議,它包括四個部分:SOAP封裝(envelop),封裝定義了一個描述消息中的內(nèi)容是什么,是誰發(fā)送的,誰應(yīng)當(dāng)接受并處理它以及如何處理它們的框架;SOAP編碼規(guī)則(encoding rules),用于表示應(yīng)用程序需要使用的數(shù)據(jù)類型的實例; SOAP RPC表示(RPC representation),表示遠程過程調(diào)用和應(yīng)答的協(xié)定;SOAP綁定(binding),使用底層協(xié)議交換信息。
3.XmlSerializer
也是保存成XML文件.但沒有其他額外信息.另外它只能保存public類型的字段.而其他兩種類型能保存所有類型的字段.
這里仍使用上面的Person類.
實例1:
添加名稱空間:
using System.IO;using System.Xml.Serialization;
序列化:
classProgram{staticvoid Main(string[] args){Person person = newPerson();person.age = 18;person.name = "tom";person.secret = "i will not tell you";FileStream stream =newFileStream(@"c:\temp\xmlFormat.xml",FileMode.Create);XmlSerializer xmlserilize = newXmlSerializer(typeof(Person));xmlserilize.Serialize(stream, person);stream.Close();}
反序列化:
classProgram{staticvoid Main(string[] args){Person person = newPerson();FileStream stream =newFileStream(@"c:\temp\xmlFormat.xml",FileMode.Open);XmlSerializerxmlserilize = newXmlSerializer(typeof(Person));person = (Person)xmlserilize.Deserialize(stream);stream.Close();Console.WriteLine(person.age + person.name + person.secret);}
指定 XML 標簽的名字
[]public class Department {public string DeptName { get; set; }[]public DeptExtraInfo DeptExtraInfo { get; set; }}
通過在 XmlRoot、XmlElement 后面加上一個括號即可實現(xiàn),其中XmlRoot用于指定“根”,也就是XML的最上一層的Tag
指定 XML 標簽的屬性
[]public class Department {public string DeptName { get; set; } = "研發(fā)部";[]public int Timestamp = 10;}
Timestamp就成為了department這個根節(jié)點的timestamp屬性。
實例2:
public class Book{public String title;}public void ReadXML(){// First write something so that there is something to read ...var b = new Book { title = "Serialization Overview" };var writer = new System.Xml.Serialization.XmlSerializer(typeof(Book));var wfile = new System.IO.StreamWriter(@"c:\temp\SerializationOverview.xml");writer.Serialize(wfile, b);wfile.Close();// Now we can read the serialized book ...System.Xml.Serialization.XmlSerializer reader =new System.Xml.Serialization.XmlSerializer(typeof(Book));System.IO.StreamReader file = new System.IO.StreamReader(@"c:\temp\SerializationOverview.xml");Book overview = (Book)reader.Deserialize(file);file.Close();Console.WriteLine(overview.title);}
傳統(tǒng)方法生成xml:(超鏈接)
【推薦】.NET Core開發(fā)實戰(zhàn)視頻課程 ★★★
.NET Core實戰(zhàn)項目之CMS 第一章 入門篇-開篇及總體規(guī)劃
【.NET Core微服務(wù)實戰(zhàn)-統(tǒng)一身份認證】開篇及目錄索引
Redis基本使用及百億數(shù)據(jù)量中的使用技巧分享(附視頻地址及觀看指南)
.NET Core中的一個接口多種實現(xiàn)的依賴注入與動態(tài)選擇看這篇就夠了
用abp vNext快速開發(fā)Quartz.NET定時任務(wù)管理界面
在ASP.NET Core中創(chuàng)建基于Quartz.NET托管服務(wù)輕松實現(xiàn)作業(yè)調(diào)度
現(xiàn)身說法:實際業(yè)務(wù)出發(fā)分析百億數(shù)據(jù)量下的多表查詢優(yōu)化
