一、前言
在用C語言編程的時候,如果要通過網絡或者串口等接口傳輸一個結構體,通常會將這個結構體指針強轉成char類型的指針,然后以char類型傳輸,在另外一邊將接收到的數據的指針再轉成想要的結構體指針即可。在C#里顯然是不能用這種方法操作的。如果用C#編程,可以將需要傳輸的對象序列化,再另外一邊再進行反序列化。
二、二進制序列化
將一個數據進行二進制序列化需要用到的類為:BinaryFormatter,需要引用的命名空間為:System.Runtime.Serialization.Formatters.Binary;
二進制序列化方法:void Serialize(Stream serializationStream, object graph);
該方法的作用是將graph序列化到指定的流。為了測試方便,可以使用FileStream對象(因為FileStream繼承自Stream)以文件的形式存儲在本地。如果序列化的是一個自定義類對象,那么該類需要用[Serializable]標記,否則程序運行時會拋出異常。
測試代碼如下:
using System; using System.Runtime.Serialization.Formatters.Binary; using System.IO; namespace Suzkfly { class Program { static void Main(string[] args) { Person zhangsan = new Person(); BinaryFormatter bf = new BinaryFormatter(); using (FileStream fs = File.Create(@"C:\Users\Suzkfly\Desktop\file_test\1.txt")) { bf.Serialize(fs, zhangsan); } } } [Serializable] public class Person { private int age = 18; private char gender = '男'; private string name = "張三"; } }
程序運行完之后在我傳入的那個路徑下就出現了1.txt,打開里面的內容大部分是亂碼,但能看到里面有age,gender,name這些字符串。
三、二進制反序列化
二進制的反序列化就是序列化的逆過程,具體內容就不多說了,直接上測試代碼,這次測試使用的1.txt就是上一章生成的,但在代碼里我故意使了一些壞:
using System; using System.Runtime.Serialization.Formatters.Binary; using System.IO; namespace Suzkfly { class Program { static void Main(string[] args) { Person zhangsan = new Person(); BinaryFormatter bf = new BinaryFormatter(); using (FileStream fs = File.OpenRead(@"C:\Users\Suzkfly\Desktop\file_test\1.txt")) { zhangsan = (Person)bf.Deserialize(fs); } Console.WriteLine("zhangsan.age = {0}", zhangsan.age); Console.WriteLine("zhangsan.gender = {0}", zhangsan.gender); Console.WriteLine("zhangsan.name = {0}", zhangsan.name); Console.ReadKey(); } } [Serializable] public class Person { public string name; public char gender; public int age; } }
反序列化也要在類上標記[Serializable],不然運行時會拋出異常。代碼中我“使壞”的地方有2處,第一是將每個字段的訪問修飾符由private改成了public,第二是調換了三個字段的順序,但是程序的運行結果是喜人的:
但是不能改變類名,否則程序運行時會拋出異常。如果改變了字段名,但是位置不改變,如將"age",改成"egg",那么程序可以正常運行,egg的值不會變成age的值。這說明反序列化是用類名和字段名去精確匹配的,不會受字段的訪問級別和順序的影響。
四、不序列化
可以在已經被[Serializable]標記過的類中的字段前,用[NonSerialized]表示這個字段不被序列化(也不能反序列化)。
測試程序:
using System; using System.Runtime.Serialization.Formatters.Binary; using System.IO; namespace Suzkfly { class Program { static void Main(string[] args) { Person zhangsan = new Person(); BinaryFormatter bf = new BinaryFormatter(); using (FileStream fs = File.OpenRead(@"C:\Users\Suzkfly\Desktop\file_test\1.txt")) { zhangsan = (Person)bf.Deserialize(fs); } Console.WriteLine("zhangsan.age = {0}", zhangsan.Age); Console.WriteLine("zhangsan.gender = {0}", zhangsan.Gender); Console.WriteLine("zhangsan.name = {0}", zhangsan.Name); Console.ReadKey(); } } [Serializable] public class Person { private string name; private char gender; [NonSerialized] private int age = 0; public string Name { get { return name; } } public char Gender { get { return gender; } } public int Age { get { return age; } } } }
在該程序中使用的序列化的文件中是有age這個字段的,但是因為運行的程序中age是被[NonSerialized]標記的,因此運行的結果,age的值仍然是0。