序列化(Serialization)是將物件轉換為可儲存或可傳輸特定格式的動作,還原序列化則是將分解後的特定格式轉換成物件,透過序列化與還原序列化,可使資料容易儲存和傳輸。
MSDN 技術文章:序列化 (1) - 概述
簡介
序列化(Serialization)是將物件轉換為可儲存或可傳輸特定格式的動作,還原序列化則是將分解後的特定格式轉換成物件,透過序列化與還原序列化,可使資料容易儲存和傳輸。
序列化類別
.NET Framework 提供兩種序列化技術:二進位序列化(Binary Serialization)和 XML 序列化(XML Serialization)。
-
二進位序列化
二進位序列化將物件序列化為二進位格式,此類型的序列化保留型別精確度,當物件被二進位序列化分解後,可以被傳送到特定儲存媒介,例如磁碟、記憶體和在網路上序列化等。 -
XML 序列化
XML 序列化則是將物件序列化為 XML 物件,以 SOAP 進行存取,與二進位序列化不同之處在於 XML 序列化只序列化公用屬性和欄位內容,而不保留型別精確度,適用於您要提供或取用資料,而不限制使用該資料的應用程式時,例如跨網路傳送。
針對這兩種序列化技術,.NET Framework 提供對應的類別:BinaryFormatter 類別 和 SoapFormatter 類別。
-
BinaryFormatter 類別
位於命名空間 System.Runtime.Serialization.Formatters.Binary 中,將物件進行二進位序列化分解,以及將分解後的物件做還原,其序列化 Serialize 方法的定義為:
public void Serialize(
Stream serializationStream,
Object graph
)
此方法傳入 Stream 資料流物件和 Object 型別物件參數,將 Object 型別物件 graph 序列化後到第一個參數資料流物件中;還原序列化 Deserialize 方法的定義為:
public Object Deserialize(
Stream serializationStream
)
此方法傳入 Stream 資料流型別參數,即是將資料流物件重新還原為被序列化的物件。
-
SoapFormatter 類別
位於命名空間 System.Runtime.Serialization.Formatters.Soap 中,此類別序列化和還原序列化的方法 Serialize 和 Deserialize,其接受與回傳的參數與 BinaryFormatter 類別相同。
當你想要將類別的實體物件序列化和還原序列換之前,必須先判斷類別是否能序列化,通常是藉由屬性 <Serializable> 做標示,接著我們舉一個例子示範序列化與還原序列化的操作。
範例說明
範例程式表單畫面如下圖所示,可選擇使用二進位或 SOAP 進行序列化與還原序列化動作,並且將序列化與還原序列化的結果顯示在表單中。
程式碼的部分,首先建立一個類別,加上 <Serializable> 屬性標示為可序列化。
[Serializable]
public class ClsSerializable
{
private int _Number;
private string _Name;
private string _Cmt;
public ClsSerializable()
{
this._Number = 7;
this._Name = "Ou";
this._Cmt = "喜歡音樂";
}
public int Number
{
get { return this._Number; }
}
public string Name
{
get { return this._Name; }
}
public string Cmt
{
get { return this._Cmt; }
}
}
建立一個方法 SerializeBinary(),使用 BinaryFormatter 類別的 Serialize 方法,傳入 ClsSerializable 類別物件來做二進位序列化,並寫入指定的檔案資料流中。
///
/// 使用 BinaryFormatter 進行序列化
///
private void SerializeBinary()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = new ClsSerializable();
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Create, FileAccess.Write))
{
// 建立 BinaryFormatter 物件
BinaryFormatter binaryFormatter = new BinaryFormatter();
// 將物件進行二進位序列化,並且儲存檔案
binaryFormatter.Serialize(fileStream, clsSerializable);
}
// 將序列化後的檔案內容呈現到表單畫面
StringBuilder sbContent = new StringBuilder();
foreach (var byteData in File.ReadAllBytes(FileName))
{
sbContent.Append(byteData);
sbContent.Append(" ");
}
this.rtbContent.Text = sbContent.ToString();
}
另外我們建立一個方法 SerializeSoap(),將ClsSerializable 類別物件透過SoapFormatter 類別的 Serialize 方法做 XML 序列化,並且儲存到指定檔案中。我們可以發現 BinaryFormatter 和 SoapFormatter 類別的序列化使用方法相同。
///
/// 使用 SoapFormatter 進行序列化
///
private void SerializeSoap()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = new ClsSerializable();
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Create, FileAccess.Write))
{
// 建立 SoapFormatter 物件
SoapFormatter soapFormatter = new SoapFormatter();
// 將物件進行 SOAP 序列化,並且儲存檔案
soapFormatter.Serialize(fileStream, clsSerializable);
}
// 將序列化後的檔案內容呈現到表單畫面
rtbContent.Text = File.ReadAllText(FileName);
}
針對二進制還原序列化的部分,建立方法 DeserializeBinary(),先做讀取檔案資料流的動作,透過 BinaryFormatter 類別的 Deserialize 方法還原序列化為 Object 物件,需要進一步做強制轉型成為正確的型別 ClsSerializable。
///
/// 使用 BinaryFormatter 進行還原序列化
///
///
private ClsSerializable DeserializeBinary()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = null;
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Open))
{
// 建立 BinaryFormatter 物件
BinaryFormatter binaryFormatter = new BinaryFormatter();
// 將檔案內容還原序列化成 Object 物件,並且進一步轉型成正確的型別 ClsSerializable
clsSerializable = (ClsSerializable)binaryFormatter.Deserialize(fileStream);
}
return clsSerializable;
}
針對 XML 還原序列化的部分,建立方法 DeserializeSoap(),先讀取檔案內容,透過 SoapFormatter 類別的 Deserialize 方法還原序列化為 Object 物件,需要進一步做強制轉型成為正確的型別 ClsSerializable。我們可以發現 BinaryFormatter 和 SoapFormatter 類別的還原序列化的使用方法相同。
///
/// 使用 SoapFormatter 進行還原序列化
///
///
private ClsSerializable DeserializeSoap()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = null;
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Open))
{
// 建立 SoapFormatter 物件
SoapFormatter soapFormatter = new SoapFormatter();
// 將檔案內容還原序列化成 Object 物件,並且進一步轉型成正確的型別 ClsSerializable
clsSerializable = (ClsSerializable)soapFormatter.Deserialize(fileStream);
}
return clsSerializable;
}
完整的程式碼如下所示:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Text;
using System.Windows.Forms;
namespace WinFormsFormatter
{
public partial class Form1 : Form
{
///
/// 序列化檔案名稱
///
string FileName = string.Format(@"{0}\{1}", Application.StartupPath,"demo.txt");
public Form1()
{
InitializeComponent();
}
#region 按鈕事件
private void btnSerialize_Click(object sender, EventArgs e)
{
if (rbBinary.Checked == true)
{
SerializeBinary();
}
else
{
SerializeSoap();
}
}
private void btnDeserialize_Click(object sender, EventArgs e)
{
ClsSerializable clsSerializable = null;
if (rbBinary.Checked)
{
clsSerializable = DeserializeBinary();
}
else
{
clsSerializable = DeserializeSoap();
}
// 顯示還原序列化後的類別物件於畫面中
string strContect = string.Format("Number: {0}\nName: {1}\nCmt: {2}", clsSerializable.Number, clsSerializable.Name, clsSerializable.Cmt);
}
#endregion
#region BinaryFormatter
///
/// 使用 BinaryFormatter 進行序列化
///
private void SerializeBinary()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = new ClsSerializable();
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Create, FileAccess.Write))
{
// 建立 BinaryFormatter 物件
BinaryFormatter binaryFormatter = new BinaryFormatter();
// 將物件進行二進位序列化,並且儲存檔案
binaryFormatter.Serialize(fileStream, clsSerializable);
}
// 將序列化後的檔案內容呈現到表單畫面
StringBuilder sbContent = new StringBuilder();
foreach (var byteData in File.ReadAllBytes(FileName))
{
sbContent.Append(byteData);
sbContent.Append(" ");
}
this.rtbContent.Text = sbContent.ToString();
}
///
/// 使用 BinaryFormatter 進行還原序列化
///
///
private ClsSerializable DeserializeBinary()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = null;
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Open))
{
// 建立 BinaryFormatter 物件
BinaryFormatter binaryFormatter = new BinaryFormatter();
// 將檔案內容還原序列化成 Object 物件,並且進一步轉型成正確的型別 ClsSerializable
clsSerializable = (ClsSerializable)binaryFormatter.Deserialize(fileStream);
}
return clsSerializable;
}
#endregion
#region SoapFormatter
///
/// 使用 SoapFormatter 進行序列化
///
private void SerializeSoap()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = new ClsSerializable();
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Create, FileAccess.Write))
{
// 建立 SoapFormatter 物件
SoapFormatter soapFormatter = new SoapFormatter();
// 將物件進行 SOAP 序列化,並且儲存檔案
soapFormatter.Serialize(fileStream, clsSerializable);
}
// 將序列化後的檔案內容呈現到表單畫面
rtbContent.Text = File.ReadAllText(FileName);
}
///
/// 使用 SoapFormatter 進行還原序列化
///
///
private ClsSerializable DeserializeSoap()
{
// 建立 ClsSerializable 類別物件
ClsSerializable clsSerializable = null;
// 建立檔案資料流物件
using (FileStream fileStream = new FileStream(FileName, FileMode.Open))
{
// 建立 SoapFormatter 物件
SoapFormatter soapFormatter = new SoapFormatter();
// 將檔案內容還原序列化成 Object 物件,並且進一步轉型成正確的型別 ClsSerializable
clsSerializable = (ClsSerializable)soapFormatter.Deserialize(fileStream);
}
return clsSerializable;
}
#endregion
[Serializable]
public class ClsSerializable
{
private int _Number;
private string _Name;
private string _Cmt;
public ClsSerializable()
{
this._Number = 7;
this._Name = "Ou";
this._Cmt = "喜歡音樂";
}
public int Number
{
get { return this._Number; }
}
public string Name
{
get { return this._Name; }
}
public string Cmt
{
get { return this._Cmt; }
}
}
}
}
當程式執行時,選擇二進制選項,按下序列化按鈕,我們可以看到序列化後的二進制資料。
還原序列化後的結果如下圖示。
選擇SOAP選項,按下序列化按鈕,我們可以看到序列化後的 XML 資料。
還原序列化後的結果如下圖示。
結語
本文說明了序列化技術和 .NET Framework 提供的序列化類別,並透過範例程式實作序列化與還原序列化,在沒有特殊考量的情況下,序列化與還原序列化的過程相當簡單,在接下來的系列文章中,將會說明在特殊狀況下較為彈性的作法。