[.net 物件導向程式設計進階] (9) 序列化(Serialization) (一) 二進位制流序列化

yubinfeng發表於2015-07-08

[.net 物件導向程式設計進階]  (9)  序列化(Serialization) (一) 二進位制流序列化 

本節導讀: 

在.NET程式設計中,經常物件導向處理完以後要轉換成另一種格式傳輸或儲存,這種將物件轉向其他資料格式的過程,即序列化(Serialization)。 

與之相反的過程就是反序列化(Deserialization)。掌握和利用好序列化和反序列化的方法,對提高面向程式設計技術很有益處。 

讀前必備: 

A.類和類的例項  [.net 物件導向程式設計基礎]  (9) 類和類的例項 

B.類的成員        [.net 物件導向程式設計基礎]  (10) 類的成員(欄位、屬性、方法)

1. 什麼是序列化和反序列化? 

序列化(Serialization):序列化是將物件狀態轉換為可保持或傳輸的格式的過程。 

反序列化(Deserialization) :與序列化相對的是反序列化,它將流轉換為物件。這兩個過程結合起來,可以輕鬆地儲存和傳輸資料。 

MFC中儲存或恢復物件的過程即為Serialization,也稱為Persistent(永續生存)。在序列化期間,物件將其當前狀態寫入到臨時或永久性儲存區(存入檔案中)。以後,可以通過從儲存區中讀取或反序列化物件的狀態,重新建立該物件。以此達到物件導向中的永續生存。

2. .NET中的序列化技術 

.NET Framework 幾種序列化技術,主要有以下幾種: 

嚴格來說只有兩種,就是二進位制序列化,和使用資料格式協定的序列化(包含XML,SOAP.JSON等) 

A. 二進位制(流)序列化(BinaryFormatter) -->(C/S方向為主) 

二進位制序列化保持型別保真度,用於在應用程式的不同呼叫之間保留物件的狀態。 

例如,通過將物件序列化到剪貼簿,可在不同的應用程式之間共享物件。您可以將物件序列化到流、磁碟、記憶體和網路等等。遠端處理使用序列化“通過值”在計算機或應用程式域之間傳遞物件。 

B. XML 序列化(XmlSerializer) -->(B/S C/S通用) 

XML序列化僅序列化公共屬性和欄位,且不保持型別保真度。對於要提供或使用資料而不限制使用該資料的應用程式時,比較有用的。由於 XML 是一個開放式標準,因此,對於通過 Web 共享資料而言,這是一個很好的選擇。

C. SOAP序列化(SoapFormatter) -->(通用,主要用於WebSerice交換資料) 

 SOAP同樣是一個開放式標準,這SOAP協議是一個在異構的應用程式之間進行資訊互動的理想的選擇 

D. WCF協議序列化(DataContractSerializer)-->(B/S方向,主要用於WCF通訊) 

F. Json序列化 (DataContractJsonSerializer-->(B/S移動開發 方向) 

Json全稱是 JavaScript 物件表示法(JavaScript Object Notation))是一種輕量級的資料交換方式。

3. 二進位制(流)序列化 

本節主要介紹二進位制(流)序列化 

二進位制(流)序列化,主要在底層(相對)通訊中使用比較頻繁,我們知道計算機是通過二進位制將資料傳輸和儲存到媒介(硬碟等),那麼我們在進行物件導向程式設計中,如何準確快速的將物件例項轉換為二進位制流,就是我們這節要介紹的內容。 

物件=》二進位制流 即二進位制流序列化 

下面,我還是使用“基礎篇”中“武林高手”的類來 通過“檔案流”建立檔案。 

首先建立資料類及序列化方法,如下: 

注意一下:[Serializable]標識 

Serializable屬性用來明確表示該類可以被序列化。

同樣的,我們可以用NonSerializable屬性用來明確表示類不能被序列化。

/// <summary>
/// 類:武林高手
/// MartialArtsMaster
/// </summary>
[Serializable]
class MartialArtsMaster
{
    /// <summary>
    /// 編號
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// 姓名
    /// </summary>
    public string Name { get; set; }
    /// <summary>
    /// 年齡
    /// </summary>
    public int Age { get; set; }
    /// <summary>
    /// 門派
    /// </summary>
    public string Menpai { get; set; }
    /// <summary>
    /// 武學
    /// </summary>
    public string Kungfu { get; set; }
    /// <summary>
    /// 級別
    /// </summary>
    public int Level { get; set; }
}

/// <summary>
/// 二進位制序列化和反序列化類
/// </summary>
public class Serializer
{
    /// <summary> 
    /// 使用二進位制序列化物件。 
    /// </summary> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static byte[] SerializeBytes(object value)
    {
        if (value == null) return null;

        var stream = new MemoryStream();
        new BinaryFormatter().Serialize(stream, value);

        //var dto = Encoding.UTF8.GetString(stream.GetBuffer()); 
        var bytes = stream.ToArray();
        return bytes;
    }

    /// <summary> 
    /// 使用二進位制反序列化物件。 
    /// </summary> 
    /// <param name="bytes"></param> 
    /// <returns></returns> 
    public static object DeserializeBytes(byte[] bytes)
    {
        if (bytes == null) return null;

        //var bytes = Encoding.UTF8.GetBytes(dto as string); 
        var stream = new MemoryStream(bytes);

        var result = new BinaryFormatter().Deserialize(stream);

        return result;
    }
}

下面是呼叫方法:

//本例名稱空間
//using System.Runtime.Serialization.Formatters.Binary;
//using System.IO;

//初始化武林高手
var master = new List<MartialArtsMaster>(){
    new MartialArtsMaster(){ Id = 1, Name = "黃蓉",    Age = 18, Menpai = "丐幫", Kungfu = "打狗棒法",  Level = 9  },
    new MartialArtsMaster(){ Id = 2, Name = "洪七公",  Age = 70, Menpai = "丐幫", Kungfu = "打狗棒法",  Level = 10 },
    new MartialArtsMaster(){ Id = 3, Name = "郭靖",    Age = 22, Menpai = "丐幫", Kungfu = "降龍十八掌",Level = 10 },
    new MartialArtsMaster(){ Id = 4, Name = "任我行",  Age = 50, Menpai = "明教", Kungfu = "葵花寶典",  Level = 1  },
    new MartialArtsMaster(){ Id = 5, Name = "東方不敗",Age = 35, Menpai = "明教", Kungfu = "葵花寶典",  Level = 10 },
    new MartialArtsMaster(){ Id = 6, Name = "林平之",  Age = 23, Menpai = "華山", Kungfu = "葵花寶典",  Level = 7  },
    new MartialArtsMaster(){ Id = 7, Name = "嶽不群",  Age = 50, Menpai = "華山", Kungfu = "葵花寶典",  Level = 8  }
};

//檔案流寫入
using (FileStream fs = new FileStream(@"F:\360同步雲盤\360同步雲盤\部落格\序列化\master.obj", FileMode.Append))
{
    var myByte = Serializer.SerializeBytes(master);
    fs.Write(myByte, 0, myByte.Length);
    fs.Close();
};

//檔案流讀取
using (FileStream fsRead = new FileStream(@"F:\360同步雲盤\360同步雲盤\部落格\序列化\master.obj", FileMode.Open))
{
    int fsLen = (int)fsRead.Length;
    byte[] heByte = new byte[fsLen];
    int r = fsRead.Read(heByte, 0, heByte.Length);
    var myObj = Serializer.DeserializeBytes(heByte) as List<MartialArtsMaster>;
    Console.WriteLine("編號---姓名---年齡---門派---武功---等級");
    myObj.ForEach(m => 
        Console.WriteLine(m.Id + "---" + m.Name + "---" + m.Age + "---" + m.Menpai + "---" + m.Kungfu + "---" + m.Level)
    );  
}

執行結果如下:

首先是建立的檔案master.obj:

 讀取執行結果如下: 

4.要點: 

A.序列化和反序列化的理解:

序列化(Serialization):序列化是將物件狀態轉換為可保持或傳輸的格式的過程。

反序列化(Deserialization) :與序列化相對的是反序列化,它將流轉換為物件。

B. .NET中的序列化技術

  註明了主要使用方向,方便小夥伴們有選擇性的學習。

(1)二進位制(流)序列化( BinaryFormatter) -->(C/S方向為主)

(2)XML 序列化(XmlSerializer) -->(B/S C/S通用)

(3)SOAP序列化(SoapFormatter -->(通用,主要用於WebSerice交換資料)

(4)WCF協議序列化(DataContractSerializer)-->(B/S方向,主要用於WCF通訊)

(5) Json序列化 (DataContractJsonSerializer)-->(B/S移動開發 方向)

==============================================================================================  

 返回目錄

 <如果對你有幫助,記得點一下推薦哦,如有有不明白或錯誤之處,請多交流>  

<對本系列文章閱讀有困難的朋友,請先看《.net 物件導向程式設計基礎》>

<轉載宣告:技術需要共享精神,歡迎轉載本部落格中的文章,但請註明版權及URL>

.NET 技術交流群:467189533    .NET 程式設計

==============================================================================================   

相關文章