當前位置: 妍妍網 > 碼農

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

2024-03-09碼農

什麽是序列化以及如何實作序列化?

序列化是透過將物件轉換為字節流,從而儲存物件或將物件傳輸到記憶體,資料庫或檔的過程。主要用途是保存物件的狀態,包括物件的數據,以便能夠在需要是重建物件。反向過程稱為 反序列化。

如上圖所示,物件 object 被序列化為 流,其中不僅包含數據、還包含物件型別的相關資訊,如版本、區域性和程式集名稱。然後可以將此流中的內容儲存到資料庫、檔或記憶體中。

序列化的用途:

透過序列化,可以執行如下操作:透過 Web 服務將物件發送到遠端應用程式、在域之間傳遞物件、以 XML 字串的形式傳遞物件透過防火墻、跨應用程式維護安全性或使用者專屬資訊。

讓物件可序列化:

需要具有物件、包含已序列化物件的一個流,以及一個 Fromatter。

System.Runtime.Serialization 包含序列化和反序列化物件所必須的類。

將 SerializableAttribute 特性套用於某個型別,以表示此型別的例項可以被序列化,如果對沒有 SerializableAttribute 特性的型別進行序列化,則會引發異常。

如果想讓類中的某個欄位不可序列化,可以使用 NonSerializedAttribute 特性。

序列化的三種型別--二進制、XML、JSON

可以使用二進制 binary 或 XML 進行序列化,在 二進制序列化中,所有內容都會被序列化,且效能也很好,使用二進制編碼來生成精簡的序列化,可以用於基於儲存或socket的網路流。

XML 序列化可提高可讀性,以及物件共享和使用的靈活性,XML 序列化將物件的公共欄位和內容或方法的參數和返回值序列化成符合特定 XML 格式的流,

System.Xml.Serialization 包含序列化和反序列化 XML 所需要的類

如果要保存運行程式過程的數據要麽保存到資料庫中,要麽新建一個普通的檔,然後把數據保存進去.但是這兩者有個缺點就是,不能把原有數據的結構也保存進去.比如一個類中的欄位值保存進去後再讀取出來必須再解析下才行.序列化技術讓你省去了解析的過程.保存後再讀取時直接得到一個 class

序列化的方式有三種:BinaryFormatter,SoapFormatter,XmlSerializer

1.BinaryFormatter

保存成二進制數據流.用法範例:

using System.IO;using System.Runtime.Serialization.Formatters.Binary;[Serializable]//如果要想保存某個 class中的欄位,必須在 class前面加個這樣attribute(C#裏面用中括弧括起來的標誌符)public classPerson{publicint age;publicstring name;[NonSerialized] //如果某個欄位不想被保存,則加個這樣的標誌publicstring 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物件.必須做下型別轉換stream.Close();Console.WriteLine(person.age + person.name + person.secret);//結果為18tom.因為secret沒有有被序列化.}

2.SoapFormatter

把數據保存成xml檔.裏面除了保存的內容還有些額外的Soap資訊.它的用法和BinaryFormatter一樣.只要把BinaryFormatter都替換成SoapFormatter就行.

把檔名改為person.xml

另外就是添加名稱空間:using System.Runtime.Serialization.Formatters.Soap;
這個名稱空調對就的程式集有時VS沒有自動參照.你必須手動去參照.選中project,右擊選擇Add Reference.在.NET的標簽下選擇

System.Runtime.Serialization.Formatters.Soap.然後點OK.

補充:SOAP(Simple Object Access Protocol )簡單物件存取協定是在分散或分布式的環境中交換資訊的簡單的協定,是一個基於XML的協定,它包括四個部份:SOAP封裝(envelop),封裝定義了一個描述訊息中的內容是什麽,是誰發送的,誰應當接受並處理它以及如何處理它們的框架;SOAP編碼規則(encoding rules),用於表示應用程式需要使用的數據型別的例項; SOAP RPC表示(RPC representation),表示遠端程序呼叫和應答的協定;SOAP繫結(binding),使用底層協定交換資訊。

3.XmlSerializer

也是保存成XML檔.但沒有其他額外資訊.另外它只能保存public型別的欄位.而其他兩種型別能保存所有型別的欄位.
這裏仍使用上面的Person類.

例項1:

添加名稱空間:

usingSystem.IO;usingSystem.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 標簽的名字

[XmlRoot(department)]public classDepartment {publicstring DeptName { get; set; } [XmlElement("extra")]public DeptExtraInfo DeptExtraInfo { get; set; }}

透過在 XmlRoot、XmlElement 後面加上一個括弧即可實作,其中XmlRoot用於指定「根」,也就是XML的最上一層的Tag

指定 XML 標簽的內容

[XmlRoot("department")]public classDepartment {publicstring DeptName { get; set; } = "研發部"; [XmlAttribute("timestamp")]publicint Timestamp = 10;}

Timestamp就成為了department這個根節點的timestamp內容。

例項2:

public classBook{ public String title; } publicvoidReadXML(){ // 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); }

傳統方法生成xml:(超連結)