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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...