C# - 序列化和反序列化.doc_第1页
C# - 序列化和反序列化.doc_第2页
C# - 序列化和反序列化.doc_第3页
C# - 序列化和反序列化.doc_第4页
C# - 序列化和反序列化.doc_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C# - 序列化和反序列化 收藏 一、序列化的概念序列化就是把一个对象保存到一个文件或数据库字段中去,反序列化就是在适当的时候把这个文件再转化成原来的对象使用。需要分清楚的概念:对象的序列化而不是类的序列化。对象的序列化表明C#提供了将运行中的对象(实时数据)写入到硬盘文件或者数据库中,此功能可以运用在需要保留程序运行时状态信息的环境下。使用序列化有两个最重要的原因:一个原因是将对象的状态永久保存在存储媒体中,以便可以在以后重新创建精确的副本;另一个原因是通过值将对象从一个应用程序域发送到另一个应用程序域中。前提:要将对象的类声明为可以序列化。最主要的作用有: 1、在进程下次启动时读取上次保存的对象的信息 2、在不同的AppDomain或进程之间传递数据 3、在分布式应用系统中传递数据 . 二、永久存储通常需要将一个对象的各字段的值存储到磁盘中,这样以后可以检索这些数据。尽管不依赖序列化也可以很容易地做到这一点,但这样的方法通常十分麻烦并且容易出错,在您需要跟踪对象的层次结构时将变得越来越复杂。设想一下编写包含数以千计对象的大型商业应用程序,将不得不为每一对象编写代码以将字段和属性保存到磁盘上和从磁盘上还原它们,这是多么的复杂。而序列化为实现上述目标提供了一个方便的机制。公共语言运行库管理对象在内存中的存储方式并通过使用反射提供自动的序列化机制。当序列化一个对象时,类的名称、程序集和类实例的所有数据成员都被写入存储中。对象通常在成员变量中存储对其他实例的引用。在序列化类时,序列化引擎跟踪已被序列化的引用对象,以确保同一对象不会被多次序列化。随 一起提供的序列化结构自动正确处理对象图和循环引用。对于对象图的唯一要求就是,由被序列化的对象引用的所有对象还必须标记为 Serializable。如果没有进行此标记,当序列化程序尝试序列化未标记的对象时,将引发一个异常。当反序列化已序列化的类时,重新创建该类并且自动还原所有数据成员的值。三、值封送对象只在创建它们的应用程序域中有效。将对象作为一个参数传递或将其作为结果返回的任何尝试都将失败,除非该对象派生自 MarshalByRefObject 或被标记为 Serializable。如果该对象被标记为 Serializable,该对象将被自动序列化,从一个应用程序域传输到其他的应用程序域,然后被反序列化以在第二个应用程序域中生成该对象的精确副本。此过程通常被称作值封送。当对象从 MarshalByRefObject 派生时,从一个应用程序域将对象引用传递到另一个应用程序域,而不是传递该对象本身。还可将从 MarshalByRefObject 派生的对象标记为 Serializable。当该对象与远程处理一起使用时,负责序列化的格式化程序(该格式化程序已由代理选择器 SurrogateSelector 预先配置)控制序列化过程,并用代理代替从 MarshalByRefObject 派生的所有对象。如果没有适当的 SurrogateSelector,则序列化结构遵循在序列化过程的步骤中描述的标准序列化规则。四、基本序列化使一个类可序列化的最简单方式是按如下所示使用 Serializable 属性标记。Serializablepublic class MyObject public int n1 = 0; public int n2 = 0; public String str = null;以下代码示例说明该类的实例是如何被序列化到一个文件中的。MyObject obj = new MyObject();obj.n1 = 1;obj.n2 = 24;obj.str = Some String;IFormatter formatter = new BinaryFormatter();Stream stream = new FileStream(MyFile.bin, FileMode.Create, FileAccess.Write, FileShare.None);formatter.Serialize(stream, obj);stream.Close();该示例使用二进制格式化程序执行序列化。您需要做的所有工作就是创建流的实例和您想要使用的格式化程序,然后对该格式化程序调用 Serialize 方法。要序列化的流和对象作为参数提供给该调用。尽管在此示例中并没有显式阐释这一点,但一个类的所有成员变量都将被序列化,即使是那些已标记为私有的变量。在此方面,二进制序列化不同于 XMLSerializer 类,后者只序列化公共字段。将对象还原回其以前的状态十分简单。首先,创建用于读取的流和格式化程序,然后指示格式化程序反序列化该对象。下面的代码示例说明如何执行上述的操作。IFormatter formatter = new BinaryFormatter();Stream stream = new FileStream(MyFile.bin, FileMode.Open, FileAccess.Read, FileShare.Read);MyObject obj = (MyObject) formatter.Deserialize(stream);stream.Close();/ Heres the proof.Console.WriteLine(n1: 0, obj.n1);Console.WriteLine(n2: 0, obj.n2);Console.WriteLine(str: 0, obj.str);上面所用的 BinaryFormatter 非常有效,生成了非常简洁的字节流。通过该格式化程序序列化的所有对象也可以通过该格式化程序进行反序列化,这使该工具对于序列化将在 .NET Framework 上被反序列化的对象而言十分理想。需要特别注意的是,在反序列化一个对象时不调用构造函数。出于性能方面的原因对反序列化施加了该约束。但是,这违反了运行库与对象编写器之间的一些通常约定,开发人员应确保他们在将对象标记为可序列化时了解其后果。如果可移植性是必需的,则转为使用 SoapFormatter。只需用 SoapFormatter 代替上面代码中的 BinaryFormatter,并且如前面一样调用 Serialize 和 Deserialize。此格式化程序为上面使用的示例生成以下输出。 1 24 Some String 需要特别注意的是,Serializable 属性不能被继承。如果我们从 MyObject 派生一个新类,此新类必须也用该属性标记,否则将无法被序列化。例如,当试图序列化下面的类的实例时,您将获得 SerializationException,通知您 MyStuff 类型没有标记为可序列化。public class MyStuff : MyObject public int n3;使用 Serializable 属性十分方便,但它具有上面所述的限制。在对类进行编译后,就不能再向该类添加序列化。五、序列化举例在C#中常见的序列化的方法主要也有三个:BinaryFormatterSoapFormatterXML序列化 本文就通过一个小例子主要说说这三种方法的具体使用和异同点:这个例子就是使用三种不同的方式把一个Book对象进行序列化和反序列化,当然这个Book类首先是可以被序列化的。 Book类 using System; using System.Collections; using System.Text; namespace SerializableTest Serializable public class Book public Book() alBookReader = new ArrayList(); public string strBookName; NonSerialized public string strBookPwd; private string _bookID; public string BookID get return _bookID; set _bookID = value; public ArrayList alBookReader; private string _bookPrice; public void SetBookPrice(string price) _bookPrice = price; public void Write() Console.WriteLine(Book ID: + BookID); Console.WriteLine(Book Name: + strBookName); Console.WriteLine(Book Password: + strBookPwd); Console.WriteLine(Book Price: + _bookPrice); Console.WriteLine(Book Reader:); for (int i = 0; i alBookReader.Count; i+) Console.WriteLine(alBookReaderi); Page 这个类比较简单,就是定义了一些public字段和一个可读写的属性,一个private字段,一个标记为NonSerialized的字段,具体会在下面的例子中体现出来 1、BinaryFormatter序列化方式 序列化,就是给Book类赋值,然后进行序列化到一个文件中 Book book = new Book(); book.BookID = 1; book.alBookReader.Add(gspring); book.alBookReader.Add(永春); book.strBookName = C#强化; book.strBookPwd = *; book.SetBookPrice(50.00); BinarySerialize serialize = new BinarySerialize(); serialize.Serialize(book); /2、反序列化 BinarySerialize serialize = new BinarySerialize(); Book book = serialize.DeSerialize(); book.Write(); /3、测试用的 BinarySerialize类 using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.Serialization.Formatters.Binary; namespace SerializableTest public class BinarySerialize string strFile = c:book.data; public void Serialize(Book book) using (FileStream fs = new FileStream(strFile, FileMode.Create) BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(fs, book); public Book DeSerialize() Book book; using (FileStream fs = new FileStream(strFile, FileMode.Open) BinaryFormatter formatter = new BinaryFormatter(); Page book = (Book)formatter.Deserialize(fs); return book; 主要就是调用System.Runtime.Serialization.Formatters.Binary空间下的BinaryFormatter类进行序列化和反序列化,以缩略型二进制格式写到一个文件中去,速度比较快,而且写入后的文件已二进制保存有一定的保密效果。 调用反序列化后的截图如下: 也就是说除了标记为NonSerialized的其他所有成员都能序列化 2、SoapFormatter序列化方式 调用序列化和反序列化的方法和上面比较类似,我就不列出来了,主要就看看SoapSerialize类 SoapSerialize类 using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Runtime.Serialization.Formatters.Soap; namespace SerializableTest public class SoapSerialize string strFile = c:book.soap; public void Serialize(Book book) using (FileStream fs = new FileStream(strFile, FileMode.Create) SoapFormatter formatter = new SoapFormatter(); formatter.Serialize(fs, book); public Book DeSerialize() Book book; using (FileStream fs = new FileStream(strFile, FileMode.Open) SoapFormatter formatter = new SoapFormatter(); book = (Book)formatter.Deserialize(fs); return book; 主要就是调用System.Runtime.Serialization.Formatters.Soap空间下的SoapFormatter类进行序列化和反序列化,使用之前需要应用System.Runtime.Serialization.Formatters.Soap.dll(.net自带的) 序列化之后的文件是Soap格式的文件(简单对象访问协议(Simple Object Access Protocol,SOAP),是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议(HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用(RPC)等大量的应用程序。SOAP使用基于XML的数据结构和超文本传输协议(HTTP)的组合定义了一个标准的方法来使用Internet上各种不同操作环境中的分布式对象。) 调用反序列化之后的结果和方法一相同 3、XML序列化方式 调用序列化和反序列化的方法和上面比较类似,主要就看看XmlSerialize类 XmlSerialize类 using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Xml.Serialization; namespace SerializableTest public class XmlSerialize string strFile = c:book.xml; public void Serialize(Book book) using (FileStream fs = new FileStream(strFile, FileMode.Create) XmlSerializer formatter = new XmlSerializer(typeof(Book); formatter.Serialize(fs, book); public Book DeSerialize() Book book; using (FileStream fs = new FileStream(strFile, FileMode.Open) XmlSerializer formatter = new XmlSerializer(typeof(Book); book = (Book)formatter.Deserialize(fs); return book; 从这三个测试类我们可以看出来其实三种方法的调用方式都差不多,只是具体使用的类不同 xml序列化之后的文件就是一般的一个xml文件: book.xml C#强化 * gspring 永春 1 输出截图如下: 也就是说采用xml序列化的方式只能保存public的字段和可读写的属性,对于private等类型的字段不能进行序列化 关于循环引用: 比如在上面的例子Book类中加入如下一个属性: public Book relationBook; 在调用序列化时使用如下方法: Book book = new Book(); book.BookID = 1; Page book.alBookReader.Add(gspring); book.alBookReader.Add(永春); book.strBookName = C#强化; book.strBookPwd = *; book.SetBookPrice(50.00); Book book2 = new Book(); book2.BookID = 2; book2.alBookReader.Add(gspring); book2.alBookReader.Add(永春); book2.strBookName = .NET强化; book2.strBookPwd = *; book2.SetBookPrice(40.00); book.relationBook = book2; book2.relationBook = book; BinarySerialize serialize = new BinarySerialize(); serialize.Serialize(book);这样就会出现循环引用的情况,对于BinarySe

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论