C# 二進制BinaryFormatter和Xml進行序列化與反序列化

序列化又稱串行化,是.NET運行時環境用來支持用戶定義類型的流化的機制。其目的是以某種存儲形成使自定義對象持久化,或者將這種對象從一個地方傳輸到另一個地方。

.NET框架提供了兩種種串行化的方式:1、是使用BinaryFormatter進行串行化;2、使用XmlSerializer進行串行化。第一種方式提供了一個簡單的二進制數據流以及某些附加的類型信息,而第二種將數據流格式化爲XML存儲。    可以使用[Serializable]屬性將類標誌爲可序列化的。如果某個類的元素不想被序列化,1、可以使用[NonSerialized]屬性來標誌,2、可以使用[XmlIgnore]來標誌。

序列化意思指的是把對象的當前狀態進行持久化,一個對象的狀態在面向對象的程序中是由屬性表示的,所以序列化類的時候是從屬性讀取值以某種格式保存下來,而類的成員函數不會被序列化,.net存在幾種默認提供的序列化,二進制序列化,xml和json序列化會序列化所有的實例共有屬性。

  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using System.Collections.Generic;
  6. using System.Runtime.Serialization.Formatters.Binary;
  7. [Serializable] // 表示該類可以被序列化
  8. class Person
  9. {
  10. private string name;
  11. [NonSerialized] // 表示下面這個age字段不進行序列化
  12. private int age;
  13. public string Name
  14. {
  15. get { return name;}
  16. set { name = value;}
  17. }
  18. public int Age
  19. {
  20. get { return age;}
  21. set { age = value;}
  22. }
  23. public Person() { }
  24. public Person(string name, int age)
  25. {
  26. this.name = name;
  27. this.age = age;
  28. }
  29. public void SayHi()
  30. {
  31. Debug.LogFormat ("我是{0}, 今年{1}歲", name, age);
  32. }
  33. }
  34. public class BinarySerializer : MonoBehaviour {
  35. string filePath = Directory.GetCurrentDirectory() + "/binaryFile.txt";
  36. // Use this for initialization
  37. void Start () {
  38. List<Person> listPers = new List<Person> ();
  39. Person per1 = new Person ("張三", 18);
  40. Person per2 = new Person ("李四", 20);
  41. listPers.Add (per1);
  42. listPers.Add (per2);
  43. SerializeMethod (listPers); // 序列化
  44. DeserializeMethod(); // 反序列化
  45. Debug.Log("Done ! ");
  46. }
  47. void DeserializeMethod() // 二進制反序列化
  48. {
  49. FileStream fs = new FileStream (filePath, FileMode.Open);
  50. BinaryFormatter bf = new BinaryFormatter ();
  51. List<Person> list = bf.Deserialize (fs) as List<Person>;
  52. if (list != null)
  53. {
  54. for (int i = 0; i < list.Count; i++)
  55. {
  56. list [i].SayHi ();
  57. }
  58. }
  59. fs.Close ();
  60. }
  61. void SerializeMethod(List<Person> listPers) // 二進制序列化
  62. {
  63. FileStream fs = new FileStream (filePath, FileMode.Create);
  64. BinaryFormatter bf = new BinaryFormatter ();
  65. bf.Serialize (fs, listPers);
  66. fs.Close ();
  67. }
  68. // Update is called once per frame
  69. void Update () {
  70. }
  71. }


序列化的文本打開後,內容如下所示:


反序列化輸出結果:

大家好,我是張三,今年0歲

大家好,我是李四,今年0歲

由此看出,未序列化的字段存儲的值爲空

使用XmlSerializer進行串行化
    關於格式化器還有一個問題,假設我們需要XML,有兩中方案:要麼編寫一個實現IFormatter接口的類,採用的方式類似於SoapFormatter類,但是沒有你不需要的信息;要麼使用庫類XmlSerializer,這個類不使用Serializable屬性,但是它提供了類似的功能。
    如果我們不想使用主流的串行化機制,而想使用XmlSeralizer進行串行化我們需要做一下修改:
    a.添加System.Xml.Serialization命名空間。
    b.Serializable和NoSerialized屬性將被忽略,而是使用XmlIgnore屬性,它的行爲與NoSerialized類似。
    c.XmlSeralizer要求類有個默認的構造器,這個條件可能已經滿足了。
序列化:

XmlSerializer xs = new XmlSerializer(typeof(List<Peoson>));
xs.Serialize(fs, listPers);
反序列化:

XmlSerializer xs = new XmlSerializer(typeof(List<Peoson>));
List<Peoson> list = xs.Deserialize(fs) as List<Peoson>;

  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. using System.Xml.Serialization;
  6. using System.Xml;
  7. using System.Collections.Generic;
  8. [Serializable] // 表示該類可以被序列化
  9. [XmlRoot("AAA")] // 設置爲XML中的根元素名稱
  10. public class Person
  11. {
  12. private string name;
  13. private int age;
  14. // [XmlElement("abc")]
  15. public int abc = 1000; // 類的public屬性字段都可以被序列化
  16. // [XmlAttribute("Name")] 設置作爲xml中的屬性
  17. public string Name
  18. {
  19. get { return name;}
  20. set { name = value;}
  21. }
  22. // [XmlElement("Age")] 設置作爲XML中的元素(默認狀態)
  23. public int Age
  24. {
  25. get { return age;}
  26. set { age = value;}
  27. }
  28. public Person() { }
  29. public Person(string name, int age)
  30. {
  31. this.name = name;
  32. this.age = age;
  33. }
  34. public void SayHi()
  35. {
  36. Debug.LogFormat ("我是{0}, 今年{1}歲", name, age);
  37. }
  38. }
  39. public class XmlSerialize : MonoBehaviour {
  40. string filePath = Directory.GetCurrentDirectory() + "/XmlFile.txt";
  41. string filePath2 = Directory.GetCurrentDirectory() + "/XmlClassFile.txt";
  42. // Use this for initialization
  43. void Start () {
  44. List<Person> listPers = new List<Person> ();
  45. Person per1 = new Person ("張三", 18);
  46. Person per2 = new Person ("李四", 20);
  47. listPers.Add (per1);
  48. listPers.Add (per2);
  49. SerializeMethod (listPers); // 序列化
  50. DeserializeMethod(); // 反序列化
  51. // SerializeClassMethod (per1);
  52. // DeserializeClassMethod ();
  53. Debug.Log("Done ! ");
  54. }
  55. void DeserializeClassMethod() // Xml實體類反序列化
  56. {
  57. FileStream fs = new FileStream (filePath, FileMode.Open);
  58. XmlSerializer xs = new XmlSerializer(typeof(Person));
  59. Person p = xs.Deserialize (fs) as Person;
  60. if (p != null)
  61. {
  62. p.SayHi ();
  63. }
  64. fs.Close ();
  65. }
  66. void SerializeClassMethod(Person p) // Xml實體類序列化
  67. {
  68. FileStream fs = new FileStream (filePath2, FileMode.Create);
  69. XmlSerializer xs = new XmlSerializer(typeof(Person));
  70. xs.Serialize(fs, p);
  71. fs.Close ();
  72. }
  73. void DeserializeMethod() // Xml列表反序列化
  74. {
  75. FileStream fs = new FileStream (filePath, FileMode.Open);
  76. XmlSerializer xs = new XmlSerializer(typeof(List<Person>));
  77. List<Person> listPers = xs.Deserialize (fs) as List<Person>;
  78. if (listPers != null)
  79. {
  80. for (int i = 0; i < listPers.Count; i++)
  81. {
  82. listPers [i].SayHi ();
  83. }
  84. }
  85. fs.Close ();
  86. }
  87. void SerializeMethod(List<Person> listPers) // Xml列表序列化
  88. {
  89. FileStream fs = new FileStream (filePath, FileMode.Create);
  90. XmlSerializer xs = new XmlSerializer(typeof(List<Person>));
  91. xs.Serialize(fs, listPers);
  92. fs.Close ();
  93. }
  94. // Update is called once per frame
  95. void Update () {
  96. }
  97. }

Xml列表序列化的內容:



Xml實體類序列化的內容:




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章