C#序列化與反序列化學習

来源:http://www.cnblogs.com/shouce/archive/2016/05/26/5529579.html
-Advertisement-
Play Games

最近為了換一份新工作,準備了不少筆試題。從筆試當中自己發現了不少基礎知識的盲點。很慶幸這樣的機會,可以讓自己對於基礎知識的理解又上升一個臺階。此文介紹C#裡面的序列化與反序列化的知識,如果你是大鳥,請口下留情。 首先,什麼是序列化與反序列化呢? 序列化就是將對象的狀態信息轉換為可以存儲或傳輸形式的過 ...


最近為了換一份新工作,準備了不少筆試題。從筆試當中自己發現了不少基礎知識的盲點。很慶幸這樣的機會,可以讓自己對於基礎知識的理解又上升一個臺階。此文介紹C#裡面的序列化與反序列化的知識,如果你是大鳥,請口下留情。

首先,什麼是序列化與反序列化呢?

序列化就是將對象的狀態信息轉換為可以存儲或傳輸形式的過程。其實就是將對象持久化,比如說把對象保存為二進位或者是XML的方式。可以將對象序列到流、磁碟、記憶體和網路等等。相反,反序列化則是將存儲或傳輸形式轉換為對象的過程。

 

那麼,運用序列化的好處又是什麼呢?

(1)以某種存儲形式(二進位或者是XML等)使對象持久化。序列化和反序列化用來保存記憶體中的數據,它不是C#中獨有的技術,比如win7的休眠就是該技術的應用,在C#程式中可以用來保存對象,和對象當前狀態,下次打開時通過反序列化獲得,一般用在伺服器啟動(反序列化)和關閉(序列化)時保存數據。

(2)使對象的傳遞更加容易,比如你用ajax向伺服器請求信息,伺服器可以直接將model對象通過序列化來輸出json字元串,也可以通過反序列化將你傳過去的json字元串組裝成對象,就免去了拼字元串和解析字元串的過程。

最後,在.Net裡面怎麼實現序列化技術?

(1)二進位序列化保持類型保真度,這對於在應用程式的不同調用之間保留對象的狀態很有用。例如,通過將對象序列化到剪貼板,可在不同的應用程式之間共用對象。您可以將對象序列化到流、磁碟、記憶體和網路等等。

(2) XML 序列化僅序列化公共屬性和欄位,且不保持類型保真度。當您要提供或使用數據而不限制使用該數據的應用程式時,這一點是很有用的。由於 XML 是一個開放式標準,因此,對於通過 Web 共用數據而言,這是一個很好的選擇。SOAP 同樣是一個開放式標準,這使它也成為一個頗具吸引力的選擇。----------以上內容摘自百科的內容與百度的內容.

關於這兩點的概念,我自己也不大明白是什麼意思?

保持類型保真度,一開始我是認為是成員變數的類型,以為用XML序列化的話,都會變成是string的類型,但是發現根本不是這樣。成員變數的類型都能保存,那這裡說的類型保真類到底是指什麼?XML序列化僅序列化公共屬性和欄位,但是我用私有欄位,發現也一樣可以序列化。我是定義一個私有欄位,然後通過公共屬性來給它賦值,然後在反序列化裡面通過公共屬性來取私有欄位的內容,發現是可以的,不知道是不是我的理解有什麼問題?

 

1#針對二進位序列化與反序列化,.Net是使用BinaryFormatter對象來進行序列化與反序列化。

一般的實現方法,是把可序列化的類用特征類[Serializable]來標誌,當然,不想序列類的成員,可以用[NonSerialized]特征類來標誌。類裡面的所有成員變數都能被序列化。然後實例化命名空間System.Runtime.Serialization.Formatters.Binary下的BinaryFormatter對象,藉助其Serialize方法來實現序列化與Deserialize方法來實現反序列化。

複製代碼
using System;
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

[Serializable]
public class SerializeObject
{
    public int ID
    {
        get;
        set;
    }

    public string UserName
    {
        get;
        set;
    }

    public string Password
    {
        get;
        set;
    }

    [NonSerialized]
    public string notSerialize;
}

public class App
{
    [STAThread]
    static void Main()
    {
        Serialize();
        Deserialize();
    }

    static void Serialize()
    {
        SerializeObject serializeObject = new SerializeObject();
        serializeObject.ID = 1;
        serializeObject.UserName = "csdbfans";
        serializeObject.Password = "csdbfans";
        serializeObject.notSerialize = "博客園";

        FileStream fs = new FileStream("DataFile.dat", FileMode.Create);

        BinaryFormatter formatter = new BinaryFormatter();
        try
        {
            formatter.Serialize(fs, serializeObject);
        }
        catch (SerializationException e)
        {
            Console.WriteLine("Failed to serialize. Reason: " + e.Message);
            throw;
        }
        finally
        {
            fs.Close();
        }
    }


    static void Deserialize()
    {
        SerializeObject serializeObject = null;

        FileStream fs = new FileStream("DataFile.dat", FileMode.Open);
        try
        {
            BinaryFormatter formatter = new BinaryFormatter();

            serializeObject = (SerializeObject)formatter.Deserialize(fs);
        }
        catch (SerializationException e)
        {
            Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
            throw;
        }
        finally
        {
            fs.Close();
        }

        Console.WriteLine("反序列Serializable的結果:ID->" + serializeObject.ID + ", UserName->"                           
+ serializeObject.UserName + ", Password->" + serializeObject.Password); Console.WriteLine("反序列化NonSerialized結果:" + serializeObject.notSerialize); } }
複製代碼

 結果為:

其實你如果進到DataFile.dat文件的話,你會發現用記事本,寫字板來打開的話,都是會出現亂碼。因為它是用二進位的方式來保存的,所以你只有是在用二進位的方式下才能看到裡面的內容。不過對於我們來說,即使看到二進位的內容,我們也不大可能知道是什麼意思。所以可能只有通過反序列化的方式來讀出文檔的內容。

2#針對XML序列化與反序列化,.Net提供了兩種方式來實現。

其一:使用XmlSerializer類將對象序列化到XML文檔中和從XML文檔反序列化出對象。

與第1點的區別,摘自寒江笠博文

(I)不使用[Serializable]特征類與[NonSerializable]特征類,只使用特征類[System.Xml.Serialization.XmlIgnoreAttribute] 來標誌哪些成員變數不需要被序列化。

(II)不能序列化私有成員變數(不確定,因為我試過可以

(III)要求被序列化的類要有一個預設的構造函數(不確定,不知道這裡的構造函數是為了什麼而需要的

複製代碼
using System;
using System.IO;
using System.Collections;
using System.Xml.Serialization;
using System.Runtime.Serialization;

public class SerializeObject
{
    public int ID
    {
        get;
        set;
    }

    public string UserName
    {
        get;
        set;
    }

    public string Password
    {
        get;
        set;
    }

    [XmlIgnoreAttribute]
    public string notSerialize;
}

public class App
{
    [STAThread]
    static void Main()
    {
        Serialize();
        Deserialize();
    }

    static void Serialize()
    {
        SerializeObject serializeObject = new SerializeObject();
        serializeObject.ID = 1;
        serializeObject.UserName = "csdbfans";
        serializeObject.Password = "csdbfans";
        serializeObject.notSerialize = "博客園";

        FileStream fs = new FileStream("DataFile.xml", FileMode.Create);
        XmlSerializer formatter = new XmlSerializer(typeof(SerializeObject));
        try
        {
            formatter.Serialize(fs, serializeObject);
        }
        catch (SerializationException e)
        {
            Console.WriteLine("Failed to serialize. Reason: " + e.Message);
            throw;
        }
        finally
        {
            fs.Close();
        }
    }


    static void Deserialize()
    {
        SerializeObject serializeObject = null;

        FileStream fs = new FileStream("DataFile.xml", FileMode.Open);
        try
        {
            XmlSerializer formatter = new XmlSerializer(typeof(SerializeObject));
            serializeObject = (SerializeObject)formatter.Deserialize(fs);
        }
        catch (SerializationException e)
        {
            Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
            throw;
        }
        finally
        {
            fs.Close();
        }

        Console.WriteLine("反序列Serializable的結果:ID->" + serializeObject.ID + ", UserName->"                           
+ serializeObject.UserName + ", Password->" + serializeObject.Password); Console.WriteLine("反序列化NonSerialized結果:" + serializeObject.notSerialize); } }
複製代碼

結果:

 其二:使用SoapFormatter類將對象序列化到XML文檔中和從XML文檔反序列化出對象。

同樣是序列化到XML文檔裡面,只不過序列化裡面包含了SOAP特有的額外信息。

SoapFormatter 和 BinaryFormatter 兩個類實現 IRemotingFormatter 介面以支持遠程過程調用 (RPC),實現 IFormatter 介面(由 IRemotingFormatter 繼承)以支持對象圖形的序列化。SoapFormatter 類還支持對 ISoapMessage 對象進行 RPC,而不必使用 IRemotingFormatter 功能。此概念來自MSDN文檔,有興趣請點擊去研讀詳細內容。

其二的方法跟第一點(1#)的實現方法基本一樣,畢竟都是實現相同的介面,有一定的共性,只是最終存儲的格式或者是傳輸的方式不一樣。

複製代碼
using System;
using System.IO;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;

[Serializable]
public class SerializeObject
{
    public int ID
    {
        get;
        set;
    }

    public string UserName
    {
        get;
        set;
    }

    public string Password
    {
        get;
        set;
    }

    [NonSerialized]
    public string notSerialize;
}

public class App
{
    [STAThread]
    static void Main()
    {
        Serialize();
        Deserialize();
    }

    static void Serialize()
    {
        SerializeObject serializeObject = new SerializeObject();
        serializeObject.ID = 1;
        serializeObject.UserName = "csdbfans";
        serializeObject.Password = "csdbfans";
        serializeObject.notSerialize = "博客園";

        FileStream fs = new FileStream("DataFile.soap", FileMode.Create);

        SoapFormatter formatter = new SoapFormatter();
        try
        {
            formatter.Serialize(fs, serializeObject);
        }
        catch (SerializationException e)
        {
            Console.WriteLine("Failed to serialize. Reason: " + e.Message);
            throw;
        }
        finally
        {
            fs.Close();
        }
    }


    static void Deserialize()
    {
        SerializeObject serializeObject = null;

        FileStream fs = new FileStream("DataFile.soap", FileMode.Open);
        try
        {
            SoapFormatter formatter = new SoapFormatter();

            serializeObject = (SerializeObject)formatter.Deserialize(fs);
        }
        catch (SerializationException e)
        {
            Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
            throw;
        }
        finally
        {
            fs.Close();
        }

        Console.WriteLine("反序列Serializable的結果:ID->" + serializeObject.ID + ", UserName->"                           
+ serializeObject.UserName + ", Password->" + serializeObject.Password); Console.WriteLine("反序列化NonSerialized結果:" + serializeObject.notSerialize); } }
複製代碼

結果為: 

複製代碼
<SOAP-ENV:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance

xmlns:xsd=http://www.w3.org/2001/XMLSchema

xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/

xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/

xmlns:clr=http://schemas.microsoft.com/soap/encoding/clr/1.0

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">


<SOAP-ENV:Body>
<a1:SerializeObject id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/assem/MyTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_x003C_ID_x003E_k__BackingField>1</_x003C_ID_x003E_k__BackingField>
<_x003C_UserName_x003E_k__BackingField id="ref-3">csdbfans</_x003C_UserName_x003E_k__BackingField>
<_x003C_Password_x003E_k__BackingField href="#ref-3"/>
</a1:SerializeObject>
</SOAP-ENV:Body>


</SOAP-ENV:Envelope>
複製代碼

 

這裡使用寒江笠博文來進行兩種技術的對比:

二進位序列化的優點:

(1)所有的類成員變數(包括只讀的)都可以被序列化

(2)性能非常好

XML序列化的優點:

(1)互操作性好

(2)不需要嚴格的二進位依賴

(3)可讀性強

這是我學習序列化與反序列化的一個過程,文中引用了不少“前人”的結果,但是文中還是有些內容不是很懂,希望還是能給大家帶來幫助,哪怕是一丁點,也足矣!如果你也喜歡,轉載時,請標明出處,謝謝!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 預熱組件下載地址:下載地址 IIS預熱模塊配置界面插件:下載地址 Warm Up設定方式: (1) 應用程式池層級:只要有需要的應用程式池的Start Mode設定AlwaysRunning就可以 (2) 站點層級:選擇你們要做預熱的站點 通過以上兩步,就完成了warm up, 簡單吧。(IIS8 ...
  • - 什麼是性能調優?(what) - 為什麼需要性能調優?(why) - 什麼時候需要性能調優?(when) - 什麼地方需要性能調優?(where) - 什麼人來進行性能調優?(who) - 怎麼樣進行性能調優?(How) - 總結 # 什麼是性能調優?(what) # ![](http://i. ...
  • 1(1)庫文件:靜態庫文件 和 共用庫文件(2)比較a.靜態庫文件: 使用靜態庫文件時,直接把代碼/指令複製到目標文件中 目標文件會顯得比較龐大,修改和維護都不方便 可以脫離靜態庫文件,效率比較高 b.共用庫文件: 使用共用庫時,將代碼/指令所對應的地址複製到目標文件 目標文件會比較小,修改和維護比 ...
  • 最近由於項目需要,需要打開防火牆功能. 公司有 arm linux 3.0x86 linux 3.2x86 linux 2.4 的三個嵌入式.都需要打開防火牆功能. 執行“whereis iptables”命令,如果結果不為空,則說明防火牆軟體已安裝 輸入iptables -L 命令查看配置 此處為 ...
  • [源碼下載] 背水一戰 Windows 10 (14) - 動畫: 線性動畫, 關鍵幀動畫 作者:webabcd介紹背水一戰 Windows 10 之 動畫 線性動畫 - ColorAnimation, DoubleAnimation, PointAnimation 關鍵幀動畫 - ColorAni ...
  • 有時候,將設計器集成到業務系統中,為用戶提供一些自定義的數據表,用戶不需要瞭解如何底層的邏輯關係和後臺代碼,只需要選擇幾張關聯的數據表,我們會根據用戶的選擇生成可供用戶直接使用的數據集。本文第一部分主要講解了,如何構造三種報表模板,第二部分主要講解了對於DataRelation類在動態綁定數據集之間 ...
  • 覆蓋類成員:通過new關鍵字修飾虛函數表示覆蓋該虛函數。一個虛函數被覆蓋後,任何父類變數都不能訪問該虛函數的具體實現。public virtual void IntroduceMyself(){...}//父類虛函數public new void IntroduceMyself(){...}//子類 ...
  • 整數或者小數:^[0-9]+\.{0,1}[0-9]{0,2}$只能輸入數字:"^[0-9]*$"。只能輸入n位的數字:"^\d{n}$"。只能輸入至少n位的數字:"^\d{n,}$"。只能輸入m~n位的數字:。"^\d{m,n}$"只能輸入零和非零開頭的數字:"^(0|[1-9][0-9]*)$" ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...