一起谈.NET技术,C#序列化与反序列化(Serializable and Deserialize)

简介:      序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。

     序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。

     我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。

     .NET公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。

当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。

     在C#中常见的序列化的方法主要也有三个:BinaryFormatter、SoapFormatter、XML序列化。本文就通过一个小例子主要说说这三种方法的具体使用和异同点。

新建一个vs2008控制台工程SerializableTest,添加一个Person类,加上[Serializable]使其可以被序列化

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SerializableTest
{
    [Serializable]
    public class Person
    {
        public string Sno { get; set; }
        public string Name { get; set; }
        public string Sex { get; set; }
        public int Age { get; set; }
        public string DisplayInfo()
        {
            return "我的学号是:" +Sno+ "\n我的名字是:"+Name + "\n我的性别为:"+Sex+"\n我的年龄:"+Age+"\n";
        }
    }
}

一、BinaryFormatter序列化方式

1、序列化:新建一个Person对象me,然后将其序列化保存到文件personInfo.txt中]

var me = new Person
                         {
                             Sno = "200719",
                             Name = "yuananyun",
                             Sex="man",
                             Age=22
                         };
            //创建一个格式化程序的实例
            IFormatter formatter = new BinaryFormatter();
            //创建一个文件流
            Stream stream = new FileStream("c:/personInfo.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, me);
            stream.Close();

执行以上代码将创建一个personInfo.txt文件,它包含了me对象的程序集信息、类名和字段信息。

2、反序列化:从文件personInfo.txt中还原一个对象

 //反序列化
        Stream destream = new FileStream("c:/personInfo.txt", FileMode.Open,
            FileAccess.Read, FileShare.Read);
            var stillme = (Person)formatter.Deserialize(destream);
            stream.Close();

整个程序如下:

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace SerializableTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建一个格式化程序的实例
            IFormatter formatter = new BinaryFormatter();
            Console.WriteLine("对象序列化开始……");
            var me = new Person
                         {
                             Sno = "200719",
                             Name = "yuananyun",
                             Sex="man",
                             Age=22
                         };
            //创建一个文件流
            Stream stream = new FileStream("c:/personInfo.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, me);
            stream.Close();
            Console.WriteLine("序列化结束!\n");
            Console.WriteLine("反序列化开始……");
            //反序列化
            Stream destream = new FileStream("c:/personInfo.txt", FileMode.Open,
            FileAccess.Read, FileShare.Read);
            var stillme = (Person)formatter.Deserialize(destream);
            stream.Close();
            Console.WriteLine("反序列化结束,输出对象信息……");
            Console.WriteLine(stillme.DisplayInfo());
            Console.ReadKey();
        }
    }
}

运行结果如下:

 注意:反序列化还原对象时,并不会调用Person类的构造函数

二、SoapFormatter序列化方式

与BinaryFormatter序列化方式类似,只需要把IFormatter formatter = new BinaryFormatter()改成 IFormatter formatter = new SoapFormatter(),并且引用程序集System.Runtime.Serialization.Formatters.Soap.dll(.net自带的)

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
namespace SerializableTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建一个格式化程序的实例
            IFormatter formatter = new SoapFormatter();
            Console.WriteLine("对象序列化开始……");
            var me = new Person
                         {
                             Sno = "200719",
                             Name = "yuananyun",
                             Sex="man",
                             Age=22
                         };
            //创建一个文件流
            Stream stream = new FileStream("c:/personInfo.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, me);
            stream.Close();
            Console.WriteLine("序列化结束!\n");
            Console.WriteLine("反序列化开始……");
            //反序列化
            Stream destream = new FileStream("c:/personInfo.txt", FileMode.Open,
            FileAccess.Read, FileShare.Read);
            var stillme = (Person)formatter.Deserialize(destream);
            stream.Close();
            Console.WriteLine("反序列化结束,输出对象信息……");
            Console.WriteLine(stillme.DisplayInfo());
            Console.ReadKey();
        }
    }
}

结果与第一种方式一样。

序列化之后的文件是Soap格式的文件(简单对象访问协议(Simple Object Access Protocol,SOAP),是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议(HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用(RPC)等大量的应用程序。SOAP使用基于XML的数据结构和超文本传输协议(HTTP)的组合定义了一个标准的方法来使用Internet上各种不同操作环境中的分布式对象。),其内容如下:

<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:Person id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/SerializableTest/SerializableTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_x003C_Sno_x003E_k__BackingField id="ref-3">200719</_x003C_Sno_x003E_k__BackingField>
<_x003C_Name_x003E_k__BackingField id="ref-4">yuananyun</_x003C_Name_x003E_k__BackingField>
<_x003C_Sex_x003E_k__BackingField id="ref-5">man</_x003C_Sex_x003E_k__BackingField>
<_x003C_Age_x003E_k__BackingField>22</_x003C_Age_x003E_k__BackingField>
</a1:Person>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

三、XML序列化方式

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Xml.Serialization;
namespace SerializableTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建一个格式化程序的实例
            XmlSerializer formatter = new XmlSerializer(typeof(Person));
            Console.WriteLine("对象序列化开始……");
            var me = new Person
                         {
                             Sno = "200719",
                             Name = "yuananyun",
                             Sex="man",
                             Age=22
                         };
            //创建一个文件流
            Stream stream = new FileStream("c:/personInfo.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, me);
            stream.Close();
            Console.WriteLine("序列化结束!\n");
            Console.WriteLine("反序列化开始……");
            //反序列化
            Stream destream = new FileStream("c:/personInfo.txt", FileMode.Open,
            FileAccess.Read, FileShare.Read);
            var stillme = (Person)formatter.Deserialize(destream);
            stream.Close();
            Console.WriteLine("反序列化结束,输出对象信息……");
            Console.WriteLine(stillme.DisplayInfo());
            Console.ReadKey();
        }
    }
}

结果与上述相同,xml序列化之后的文件就是一般的一个xml文件,personInfo.txt内容如下:

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Sno>200719</Sno>
  <Name>yuananyun</Name>
  <Sex>man</Sex>
  <Age>22</Age>
</Person>

注意:采用xml序列化的方式只能保存public的字段和可读写的属性,对于private等类型的字段不能进行序列化

下面进行验证

将Person的Name属性改成Private,然后查看生成的personInfo.text,其内容如下:

<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Sno>200719</Sno>
  <Sex>man</Sex>
  <Age>22</Age>
</Person>

可以看到Name属性并没有出现在该文件中,反序列化生成的对象中Name属性值为NULL。

以上对c#序列化和反序列化的三种方式进行了举例说明。当然您也可以决定一个类中那些属性序列化或不序列化,可以通过使用 NonSerialized 属性标记成员变量来防止它们被序列化,具体内容请查阅相关资料。

目录
相关文章
|
1月前
|
Java 物联网 C#
C#/.NET/.NET Core学习路线集合,学习不迷路!
C#/.NET/.NET Core学习路线集合,学习不迷路!
|
6天前
|
开发框架 监控 .NET
C#进阶-ASP.NET WebForms调用ASMX的WebService接口
通过本文的介绍,希望您能深入理解并掌握ASP.NET WebForms中调用ASMX WebService接口的方法和技巧,并在实际项目中灵活运用这些技术,提高开发效率和应用性能。
23 5
|
14天前
|
算法 Java 测试技术
Benchmark.NET:让 C# 测试程序性能变得既酷又简单
Benchmark.NET是一款专为 .NET 平台设计的性能基准测试框架,它可以帮助你测量代码的执行时间、内存使用情况等性能指标。它就像是你代码的 "健身教练",帮助你找到瓶颈,优化性能,让你的应用跑得更快、更稳!希望这个小教程能让你在追求高性能的路上越走越远,享受编程带来的无限乐趣!
61 13
|
1月前
|
人工智能 开发框架 前端开发
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
C#/.NET/.NET Core技术前沿周刊 | 第 12 期(2024年11.01-11.10)
|
1月前
|
开发框架 网络协议 .NET
C#/.NET/.NET Core优秀项目和框架2024年10月简报
C#/.NET/.NET Core优秀项目和框架2024年10月简报
|
22天前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
|
22天前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(下)
本文接续前文,深入讲解了在Windows环境下使用C#和ADO.NET操作南大通用GBase 8s数据库的方法。通过Visual Studio 2022创建项目,添加GBase 8s的DLL引用,并提供了详细的C#代码示例,涵盖数据库连接、表的创建与修改、数据的增删查改等操作,旨在帮助开发者提高数据库管理效率。
|
1月前
|
人工智能 开发框架 安全
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
C#/.NET/.NET Core技术前沿周刊 | 第 13 期(2024年11.11-11.17)
|
1月前
|
网络协议 Unix Linux
精选2款C#/.NET开源且功能强大的网络通信框架
精选2款C#/.NET开源且功能强大的网络通信框架
|
1月前
|
程序员 C# 图形学
全面的C#/.NET自学入门指南
全面的C#/.NET自学入门指南