對象序列化是將對象(比如Person對象)轉換爲二進制數據(字節流),反序列化是將二進制數據還原爲對象。對象是稍縱即逝的,不僅程序重啓、操作系統重啓會造成對象的消失,就是退出函數範圍等都可能造成對象的消失,序列化/反序列化就是爲了保持對象的持久化。就像用DV錄像(序列化)和用播放器播放(反序列化)一樣。對象序列化,只能針對對象的字段進行序列化。以下爲序列化與反序列化兩個示例。
示例1:序列化
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;//需要引用的命名空間
namespace _05對象序列化
{
class Program
{
//總結:
//對象→byte[]序列化一個對象,但對象中可以包含多種內容,一個集合也可以
//作用:1.直接存儲對象;2.在網絡中可以直接發送對象信息
//序列化步驟:1.序列化對象:BinaryFormatter bf = new BinaryFormatter();
//2.創建文件流: using (FileStream fs=new FileStream("", FileMode.Create))
//{
//調用Serialize方法進行序列化
//bf.Serialize(fs, sly);
//}
//3.只序列化字段信息,方法不被序列化
//反序列化步驟:1.創建二進制序列化器(格式化器):BinaryFormatter bf = new BinaryFormatter();
//2.創建文件流: using (FileStream fs=new FileStream("", FileMode.Create))
//{
//調用Deserialize方法進行反序列化
//bf.Deserialize(fs);
//}
//序列化注意問題:
//1.要被序列化的對象的類型必須標記爲可序列化爲[Sreializable]
//2.父類也要標記
//3.類中字段或屬性的類型也必須爲可序列化的
static void Main(string[] args)
{
Person sly = new Person();
sly.Name = "麥兜兜";
sly.Age = 16;
sly.Email = "[email protected]";
sly.MyCar = new Car("QQ");
//現在要想存儲sly這個對象,只能是,將【"麥兜兜",16,"[email protected]"】,只能將這些數據存儲起來,
//下次用這些數據的時候,必須重新創建一個對象,然後這個對象的屬性中的值,是來源於上個對象的。。
//思考:能不能直接把sly這個對象存儲起來。這樣的話,下次使用的時候直接拿來就是一個對象,不需要重新創建。
//對象序列化的步驟
//1.創建二進制對象序列化器
BinaryFormatter bf = new BinaryFormatter();
//創建一個文件流
using (FileStream fs = new FileStream("", FileMode.Create))
{
//2.開始執行序列化
//將對象sly,序列化到fs文件流中,最終sly就保存到了根目錄(Debug)person.bin文件中。
bf.Serialize(fs, sly);
}
Console.WriteLine("ok");
Console.ReadKey();
}
}
//Person類型要想被序列化,
//1.必須Person類型本身是可序列化的(即Person類型標記爲可序列化)
//2.類中所有的字段屬性的類型也必須標記爲可序列化的
//3.當前類型的所有父類也必須標記爲可序列化的
[Serializable]
public class Person : ShenWu
{
//4.建議,在使用序列化的時候儘量避免使用自動屬性,因爲自動屬性,每次編譯的時候自動生成的字段名可能不一樣,所以在反序列化的時候可能會造成問題。
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
private int _age;
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
private string _email;
public string Email
{
get
{
return _email;
}
set
{
_email = value;
}
}
private Car _myCar;
public Car MyCar
{
get { return _myCar; }
set { _myCar = value; }
}
}
[Serializable]
public class ShenWu//Person繼承該類,所以也需要進行可序列化標記[Serializable]
{
public void Say()
{
Console.WriteLine("新陳代謝!");
}
}
[Serializable]
public class Car//Car作爲Person中的屬性字段,也需要進行可序列化標記[Serializable]
{
public Car(string brand)
{
this.Brand = brand;
}
private string _brand;
public string Brand
{
get
{
return _brand;
}
set
{
_brand = value;
}
}
}
}
說明:非網絡流中需要添加序列化集引用,在本例中即添加“05對象序列化”
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using _05對象序列化;
namespace _06反序列化
{
class Program
{
static void Main(string[] args)
{
//反序列化步驟:
//1.創建二進制序列化器(格式化器)
BinaryFormatter bf = new BinaryFormatter();
using (FileStream fs = new FileStream("person.bin", FileMode.Open))
{
//2.開始執行反序列化
//在執行反序列化的時候,由於person.bin中是存儲的是原來Person類型序列化後的結果,
//所以要對person.bin反序列化時,需要Person類所在的程序集。
//問題:爲什麼反序列化的時候需要原來定義Person類的那個程序集?
//反序列話的時候,要返回一個對象,這個對象必須根據原來Person所在的程序集才能創建,
//也就是說person.bin中包含的僅僅是一些數據,根據這些數據是無法在內存中創建對象的。
//只能是根據原來Person類型的程序集來創建對象,然後把person.bin中的數據一一對應進行賦值。
//object obj = bf.Deserialize(fs);
//對象序列化,只是對對象的一些狀態信息進行序列化(比如:字段)。
//對於方法之類的根本不進行序列化,也就是說person.bin中只包含字段名和字段值,根本沒有方法信息。
//但是反序列化的時候,返回的是一個對象,那麼只根據這些字段信息是無法創建對象的,所以這個時候
//需要先根據原來的程序集,獲取Person類型,然後在內存中創建一個Person對象,然後再把反序列化得到的字段信息賦值給這個Person對象。
Person per = (Person)bf.Deserialize(fs);//此處“Person”即“05對象序列化”中定義的Person類
Console.WriteLine("Name:{0},Age:{1},Car:{2}", per.Name, per.Age, per.MyCar.Brand);
}
Console.WriteLine("ok");
Console.ReadKey();
}
}
}