C# 二進制序列化和反序列化(初探)


一、前言

  在用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。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM