c# .net 中的序列化
正值清明节小长假有时间看了看c#.net中的序列化的部分,感觉学了点东西就顺手记了下来,希望对大家的学习也有些许的帮助。
闲言少叙,开始进入正题。
什么是序列化
根据msdn的定义:序列化是将对象的状态信息转换为可以存储或传输的形式的过程。序列化的补集是反序列化,后者将流转化为对象。这两个过程一起保证数据易于存储和传输。这个地方我们可以这样理解:对象是在程序运行过程中产生的,对象在内存上,有时候我们需要这个对象持久化也就是想长久的保存这个对象,所以就必须把对象从内存中转存在我们的硬盘上或其他介质上;还有一种情况就是两个应用程序域之间共享一个对象从而构建分布式对象,可以举一个例子:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。(注:我对分布式对象不是很了解,希望有懂的大侠赐教)总而言之,有时候实际的需要让我们把一个对象从内存中取出来用于共享或写入储存介质而实现对象的持久化。到底序列化一个对象有什么好处呢?答案是这样的:采用数据流来存储 ,以数据流传输会提高网络传输速度,在数据流进行操作可以直接操作数据流,减少数据出错的几率。
还是不懂??!呵呵,其实我一开始学的时候也是这样的感觉。不要放弃,下面我用实际生活的一个例子来说明序列化这个神秘的东东。
大家平时经常用office系列吧不管是ms office还是我们的wps,没用过?那你肯定迷路了,这个地方不适合你。呵呵。就那其中的word用在我下面的例子中吧,我们可以把word这个工具看做是一个类,用word工具产生的一个一个的word文档是一个个的对象。有人会问了word文档不是存储在磁盘介质上的吗?而对象一般情况是存在于内存中的,对象和word文档有什么牵连呢?其实我们在编辑word文档的时候,所有的数据时存放在用户机器的内存上的,当我们单击保存按钮的时候我们的数据才会被写到磁盘上。word文档从内存到硬盘的过程就相当于对象的序列化。
什么时候用序列化
a. 一个原因是将对象的状态保持在存储媒体中,以便可以在以后重新创建精确的副本。
我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。
b.另一个原因是通过值将对象从一个应用程序域发送到另一个应用程序域中。
例如,序列化可用于在 ASP.NET 中保存会话状态并将对象复制到 Windows 窗体的剪贴板中。远程处理还可以使用序列化通过值将对象从一个应用程序域传递到另一个应用程序域中。
公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。
当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。
.net中提供了哪些把一个对象序列化的方法
.net中主要提供两种技术将一个对象序列化:
(当然在序列化的同时对应一个反序列化的方法,这样的对象序列化被用于共享或用于网路的传输才显得有意义)
a.二进制序列化,采用中技术可以使类型保真,这对于多次调用应用程序时保持对象状态非常有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等。远程处理使用序列化,“按值”在计算机或应用程序域之间传递对象。
下面是我做练习的时候的一段源代码,贴出来和大家分享一下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
namespace serialization
{
[System.Serializable]//只有对象被标记为可序列化之后方可进行系列化操作,否则会发生错误!s
public class person
{
public string name { get; set; }
public int age { get; set; }
public void eat(string foodName)
{
Console.WriteLine(name+"eat"+foodName);
}
}
class Program
{
static void Main(string[] args)
{
//创建一个对象
person worker = new person();
worker.name = "kernal";
worker.age = 20;
//对象的序列化
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
//创建一个流
MemoryStream ms = new MemoryStream();
bf.Serialize(ms,worker);
//将流转化为字节数组然后输出到屏幕上
byte[] buffer = ms.ToArray();
Console.WriteLine(BitConverter.ToString(buffer));
//将字节数组转化为字符用于web开发当中
string base64 = Convert.ToBase64String(buffer);
//将base64 的字符创打印在屏幕上
Console.WriteLine(base64);
//将流还原为一个对象
worker = null;
ms.Seek(0,SeekOrigin.Begin);
object obj = bf.Deserialize(ms);
person secondWorker = obj as person;
//打印被存储对象的name和age信息
Console.WriteLine(secondWorker.name);
Console.WriteLine(secondWorker.age);
//将base64还原为字节数组
byte[] buffer2 = Convert.FromBase64String(base64);
//将还原的字节数组打印在屏幕上
Console.WriteLine(BitConverter.ToString(buffer2));
foreach (byte b in buffer2)
{
Console.Write(b);
}
Console.ReadKey();
}
}
}
b.XML 序列化 这样只序列化公共属性和字段,并且不保持类型保真。当您希望提供或使用数据而不限制使用该数据的应用程序时,这一点非常有用。由于 XML 是开放式的标准,因此它对于通过 Web 共享数据来说是一个理想选择。SOAP 同样是开放式的标准,这使它也成为一个理想选择。
更多的关于序列化的很多例子,可以参考下面的这位园友的文章
http://www.cnblogs.com/Tim_Liu/archive/2010/11/09/1872587.html