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)可读性强。

 

这是我学习序列化与反序列化的一个过程,文中引用了不少“前人”的结果,但是文中还是有些内容不是很懂,希望还是能给大家带来帮助,哪怕是一丁点,也足矣!如果你也喜欢,转载时,请标明出处,谢谢!

(Dot)Net Study

 
摘要: 最近为了换一份新工作,准备了不少笔试题。从笔试当中自己发现了不少基础知识的盲点。很庆幸这样的机会,可以让自己对于基础知识的理解又上升一个台阶。此文介绍C#里面的序列化与反序列化的知识,如果你是大鸟,请口下留情。 首先,什么是序列化与反序列化呢? 序列化就是将对象的状态信息转换为可以存储或传输形式的过程。其实就是将对象持久化,比如说把对象保存为二进制或者是XML的方式。可以将对象序列到流、磁盘、内存和网络等等。相反,反序列化则是将存储或传输形式转换为对象的过程。阅读全文
posted @ 2012-02-14 10:06 csdbfans 阅读(402) | 评论 (5) 编辑


摘要: 本文将带大家来学习一下Ajax.BeginForm与Jquery UI(Dialog)。 题外话,Hmtl.BeginForm与Ajax.BeginForm的差别,用Html.BeginForm()来提交的话,相当于提交整个页面,而使用Ajax.BeginForm来提交的话,相当于用Ajax的方式来提交。用AJAX来提交,能实现异步的交互方式,从而实现局部页面的刷新,增强用户体验。 关于Jquery UI,大家可以到官网下载所需要的脚本及样式文件。本文只介绍Jquery UI里面的Dialog,但是至少你还得下载四个脚本文件,分别勾上Core、Widget、Position和Dialog。下载完之后,把里面的一些样式、脚本文件及图像加载到我们新建的项目里面,这里面以MVC2(ASP.NET MVC2 Web Application)来作为实例说明。为了更方便大家来看到效果,我上传了源码,大家需要的话,可以通过此链接来进行下载。加载需要的Jquery UI的文件这部分我就不进行说明了,这里面有一点大家需要注意的,就是导入Jquery UI的脚本文件的时候,是有顺序之分的。大家阅读全文
posted @ 2012-01-08 13:25 csdbfans 阅读(1586) | 评论 (2) 编辑


摘要: Wcf Rest服务,是一种Web服务。Web服务是一种面向服务的架构技术,通过标准的Web协议提供服务(Web Service),它的好处是可以让不同的平台应用实现互连,进而达到数据的交换。Web服务可以说是一组工具的集合,可以用多种方式来调用。比较常用的方式有三种:远程过程调用(RPC),面向服务架构(SOA)以及表述性状态转换(REST)。 这里面,我们只介绍REST的实现,结合.net的WCF来实现。 在开始这一讲之前,还需要再补一点概念方面的内容来帮助大家进一步理解里面的知识点。REST 从资源的角度来观察整个网络,整个网络的资源由URI确定,而客户端的应用只需要通过URI来获取资源的表征。获得这些表征致使这些应用程序转变了其状态。随着不断获取资源的表征,客户端应用不断地在转变着其状态,这就是所谓的表征状态转移(Representational State Transfer)。其实这里面的概念说直白些,就是通过URI的渠道,我们能得到我们想要的资源。资源的方式可以是XML、JSON或者是HTML,取决于读者是机器还是人,是消费web服务的客户软件还是web浏览器。阅读全文
posted @ 2011-12-19 23:34 csdbfans 阅读(778) | 评论 (2) 编辑


摘要: XML(EXensible Markup Language),可扩展标记语言。 本文并不对它的概念进行详细介绍,取而代之的是说说在.Net下怎么去操作XML文件。点一下题外话,XML是标准通用标记语言(SGML)的子集,可以跨平台运行,非常适合Web传输,在不同的编程语言(PHP、Java、.Net等)里面都有广泛运用,所以对于XML的操作,将是你必须掌握的一门技术。 下面我们来看看XML文档是长什么样子的,这里将要以下图为例来进行说明。XML可以用来描述数据定义、类型等,它一般是被用作数据存储和数据传输...阅读全文
posted @ 2011-11-25 08:28 csdbfans 阅读(794) | 评论 (4) 编辑


摘要: 实现多语言版本的支持,就是所谓的国际化,也说是本地化。 今天这里将要介绍的是.Net里面实现本地化的介绍。网上有很多文章介绍怎么实现本地化,但是大多不适合初学者去学习,因为初学者需要更为详细的介绍以及图表作为说明。所以本着互相学习的想法,我也写一下自己最近学习的有关这方面的内容。阅读全文
posted @ 2011-10-17 13:07 csdbfans 阅读(1788) | 评论 (17) 编辑


原文地址:https://www.cnblogs.com/Leo_wl/p/2350747.html