C#三十一 序列化與反序列化

序列化又稱串行化,是.NET運行時環境用來支持用戶定義類型的流化的機制。其目的是以某種存儲造成使自定義對象持久化,或者將這種對象從一個地方傳輸到另外一個地方。
    .NET框架提供了兩種串行化的方式:一、是使用BinaryFormatter進行串行化;二、使用SoapFormatter進行串行化;三、使用XmlSerializer進行串行化。第一種方式提供了一個簡單的二進制數據流以及某些附加的類型信息,而第二種將數據流格式化爲XML存儲;第三種其實和第二種差很少也是XML的格式存儲,只不過比第二種的XML格式要簡化不少(去掉了SOAP特有的額外信息)。
    可使用[Serializable]屬性將類標誌爲可序列化的。若是某個類的元素不想被序列化,一、2可使用[NonSerialized]屬性來標誌,二、可使用[XmlIgnore]來標誌。服務器

 

 

重點:框架

Ø      理解序列化 / 反序列化概念函數

Ø      可以使用序列化/反序列化保持和恢復對象狀態工具

 

 

預習功課:測試

Ø      序列化的概念this

Ø      反序列化的概念spa

Ø      如何使用序列化和反序列化保持和恢復對象狀態orm

Ø      如何利用序列化來操做Xml文件xml

 

 

 

8.1 序列化和反序列化簡介對象

C#序列化和反序列化,二者的程序處理方式基本一致,都是基於工廠模式的,所謂C#序列化就是是將對象轉換爲容易傳輸的格式的過程,通常狀況下轉化打流文件,放入內存或者IO文件中。例如,能夠序列化一個對象,而後使用 HTTP 經過 Internet 在客戶端和服務器之間傳輸該對象,或者和其它應用程序共享使用。相反的,反序列化根據流從新構造對象。.NET自帶的有兩種序列化對象的方式,Xml和binary的,XML 序列化不轉換方法、索引器、私有字段或只讀屬性(只讀集合除外)。要序列化對象的全部字段和屬性(公共的和私有的),請使用 BinaryFormatter,而不要使用 XML 序列化。

8.1.1 C#序列化和反序列化的實例應用剖析:

二進制的C#序列化的方式:

例如咱們有個對象:

1.            [Serializable]public class ClassToSerialize{ 

2.            public int id=100; 

3.            public string name="Name";  

4.            }  

須要序列化該對象,必須在給該類加上Serializable的屬性,而後建立一個序列化寫入的流:FileStream fileStream = new FileStream("temp.dat",FileMode.Create);而後建立二進制格式器:BinaryFormatter b=newBinaryFormatter();而後是序列化:b.Serialize(fileStream,c);,而後關閉保存流。(能夠見下面的例子)

讀取一個已經被序列化的對象的時候:操做方式同樣,只是

5.           FileStream fileStream = new FileStream(  

6.           "temp.dat", FileMode.Open,  

7.           FileAccess.Read, FileShare.Read);  

8.           ClassToSerialize c =  

9.           (ClassToSerialize)b.Deserialize(fileStream); 

而後就能夠讀取了,完整的例子是:

10.       using System;  

11.       using System.IO;  

12.       using System.Runtime.Serialization;  

13.       using System.Runtime.Serialization.Formatters.Binary;  

14.       public class SerialTest{  

15.       public void SerializeNow(){  

16.       ClassToSerialize c=new ClassToSerialize();  

17.       FileStream fileStream = new FileStream(  

18.       "temp.dat", FileMode.Create); 

19.        

20.       BinaryFormatter b=new BinaryFormatter();  

21.       b.Serialize(fileStream,c);  

22.       fileStream.Close();  

23.       }  

24.       public void DeSerializeNow(){  

25.       ClassToSerialize c=new ClassToSerialize();  

26.       FileStream fileStream = new FileStream(  

27.       "temp.dat", FileMode.Open, 

28.        FileAccess.Read,  

29.        FileShare.Read);  

30.       BinaryFormatter b=new BinaryFormatter();  

31.       //SoapFormatter  

32.       c=(ClassToSerialize)b.Deserialize(fileStream);  

33.       Console.WriteLine(c.name);  

34.       fileStream.Close();  

35.       }  

36.       public static void Main(string[] s){  

37.       SerialTest st=new SerialTest();  

38.       st.SerializeNow();  

39.       st.DeSerializeNow();  

40.       }  

41.       }  

42.       [Serializable]  

43.       public class ClassToSerialize{  

44.       public int id=100;  

45.       public string name="Name";  

46.       }  

這就是自帶的序列化和反序列的操做,可是,不少狀況下,一個對象比較大,並且不少私有的屬性和方法咱們不須要,例如在原型模式裏面序列化的話,只須要序列Clone方法和一些屬性,私有的方法無須要,還例如在讀取大規模的IO的時候,讀取操做徹底不須要... 這時候就須要本身集成重寫序列的ISerializable接口:

實現該接口須要兩個注意的,一個就是構造函數,主要是爲了反序列,另外一個就是GetObjectData,主要是執行序列化,例如咱們如今有一個Employee類須要序列化

47.       [Serializable()]  

48.       //Set this attribute to all the classes that want to serialize 

49.       public class Employee : ISerializable   

50.       //derive your class from ISerializable { 

51.       public int EmpId;  

52.       public string EmpName;  

53.       [NonSerialized()]  

54.       public string NoSerialString="NoSerialString-Test";  

55.        

56.       } 

須要注意的是我這裏的NoSerialString屬性前面有[NonSerialized()],就是說默認並不序列化這個屬性,而是使用默認值。

首先是構造函數:

57.       public Employee(SerializationInfo info, StreamingContext ctxt) 

58.       {  

59.       EmpId = (int)info.GetValue(  

60.       "EmployeeId"typeof(int));  

61.       EmpName = (String)info.GetValue(  

62.       "EmployeeName"typeof(string));  

63.       //NoSerialString =   

64.       //(String)info.GetValue("NoSerialString", typeof(string)); 

65.       } 

而後是C#序列化方法,就是當寫入流的時候怎麼保存的:

66.       public void GetObjectData(SerializationInfo info, StreamingContext ctxt) {  

67.        

68.       info.AddValue("EmployeeId", EmpId);  

69.       info.AddValue("EmployeeName", EmpName);  

70.       } 

把上面兩個方法寫入到Employee類,而後寫個測試的程序:

71.       public class ObjSerial{  

72.       public static void Main(String[] args){  

73.       Employee mp = new Employee();  

74.       mp.EmpId = 10;  

75.       mp.EmpName = "Omkumar";  

76.       mp.NoSerialString = "你好啊";  

77.        

78.          //C#序列化和反序列化之序列化  

79.       Stream stream = File.Open("EmployeeInfo.osl", FileMode.Create); 

80.       BinaryFormatter bformatter = new BinaryFormatter(); 

81.        

82.       Console.WriteLine("Writing Employee Information");  

83.       bformatter.Serialize(stream, mp);  

84.       stream.Close();  

85.        

86.        

87.       mp = null;  

88.          //C#序列化和反序列化之反序列  

89.       stream = File.Open("EmployeeInfo.osl", FileMode.Open); 

90.       bformatter = new BinaryFormatter();  

91.        

92.       Console.WriteLine("Reading Employee Information");  

93.       mp = (Employee)bformatter.Deserialize(stream);  

94.       stream.Close();  

95.        

96.       Console.WriteLine(  

97.       "Employee Id: {0}",mp.EmpId.ToString()); 

98.       Console.WriteLine(  

99.       "Employee Name: {0}",mp.EmpName);  

100.     Console.WriteLine( 

101.     "Employee NoSerialString: {0}",mp.NoSerialString); 

102.      

103.     }  

104.     }  

C#序列化和反序列化程序執行的結果是:

105.     Writing Employee Information 

106.     Reading Employee Information 

107.     Employee Id: 10 

108.     Employee Name: Omkumar 

109.     Employee NoSerialString: NoSerialString-Test 

看到Employee NoSerialString:屬性的值沒有,它保持默認值,沒有序列化。

 

 

8.2 Xml格式序列化及反序列化

 

要序列化的對象的類:   [Serializable]   public class Person   {   private string name;   public string Name   {   get   {   return name;   }   set   {   name=value;   }   }   public string Sex;   public int Age=31;   public Course[] Courses;   public Person()   {   }   public Person(string Name)   {   name=Name;   Sex="男";   }   }   [Serializable]   public class Course   {   public string Name;   [XmlIgnore]public string Description;   public Course()   {   }   public Course(string name,string description)   {   Name=name;   Description=description;   }   }   進行序列化及反序列化的測試類:   class Test   {   //序列化   public void Serialiaze()   {   Person c=new Person("cyj")   c.Courses=new Course[2];   c.Courses[0]=new Course("英語","交流工具")   c.Courses[1]=new Course("數學","天然科學")   XmlSerializer xs=new XmlSerializer(typeof(Person));   Stream stream = newFileStream("c:\\cyj.xml", FileMode.Create, FileAccess.Write,FileShare.ReadWrite);   xs.Serialize(stream, c);   stream.Close();   }   //反序列化   public void Deserialize()   {   XmlSerializer xs=new XmlSerializer(typeof(Person));   Stream stream = newFileStream("c:\\cyj.xml", FileMode.Open, FileAccess.Read,FileShare.ReadWrite);   Person p=(Person)xs.Deserialize(stream);   Console.WriteLine(p.Name);   Console.WriteLine(p.Age.ToString());   Console.WriteLine(p.Courses.Length.ToString());   Console.Read();   }   }   格式化後Xml的文檔內容爲:   <?xml version="1.0"?>   <Person xmlns:xsd=http://www.w3.org/2001/XMLSchemaxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">   <Sex>男</Sex>    <Age>31</Age>    <Courses>    <Course>       <Name>英語</Name>    </Course>    <Course>       <Name>數學</Name>    </Course>    </Courses>       <Name>cyj</Name>   </Person>

相關文章
相關標籤/搜索