c#基础语言编程-序列化
引言
程序员在编写应用程序的时候往往要将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯。这个将程序数据转化成能被存储并传输的格式的过程被称为”序列化”(Serialization),而它的逆过程则可被称为”反序列化”(Deserialization)。通俗上讲,假如程序在运行的时候,内存中有一个对象,如果你想把这个对象的某些信息或者所有信息保存在本地,下次程序打开后,能够直接还原这个对象,怎么才能做到呢?
.Net框架对序列化机制具有非常好的支持,常用的为
二进制格式器(Binary Formatter) 、 XML格式器(XML Formatter)
不过在实际的应用中,二进制格式器往往应用于一般的桌面程序和网络通讯程序中,而XML格式器禀承了XML技术的优点,大多数被应用于.Net Remoting和XML Web服务等领域。下面我们来分析一下两种格式器各自的优点。
xml序列化
使用XML序列化或反序列化时,需要对XML序列化器指定需要序列化对象的类型和其关联的类型。
XML序列化只能序列化对象的公有属性,并且要求对象有一个无参的构造方法,否者无法反序列化。
[Serializable]和[NonSerialized]特性对XML序列化无效!所以使用XML序列化时不需要对对象增加[Serializable]特性。
public class Person
{
public string Name;//姓名
public bool Sex;//性别,是否是男
public Person() { }//必须提供无参构造器,否则XmlSerializer将出错
public Person(string name, bool sex)
{
this.Name = name;
this.Sex = sex;
}
public override string ToString()
{
return "姓名:" + this.Name + "\t性别:" + (this.Sex ? "男" : "女");
}
/// <summary>
/// 对象序列化成 XML String
/// </summary>
public string XmlSerialize<T>(T obj)
{
string xmlString = string.Empty;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
xmlSerializer.Serialize(ms, obj);
xmlString = Encoding.UTF8.GetString(ms.ToArray());
}
return xmlString;
}
// <summary>
/// XML String 反序列化成对象
/// </summary>
public T XmlDeserialize<T>(string xmlString)
{
T t = default(T);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
//此处用的是MemoryStream
using (Stream xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
{
using (XmlReader xmlReader = XmlReader.Create(xmlStream))
{
Object obj = xmlSerializer.Deserialize(xmlReader);
t = (T)obj;
}
}
return t;
}
二进制序列化
使用二进制序列化,必须为每一个要序列化的的类和其关联的类加上[Serializable]特性,对类中不需要序列化的成员可以使用[NonSerialized]特性。
二进制序列化对象时,能序列化类的所有成员(包括私有的),且不需要类有无参数的构造方法。
使用二进制格式序列化时,它不仅是将对象的字段数据进行持久化,也持久化每个类型的完全限定名称和定义程序集的完整名称(包括包称、版本、公钥标记、区域性),这些数据使得在进行二进制格式反序列化时亦会进行类型检查。所以反序列化时的运行环境要与序列化时的运行环境要相同,要记得添加引用,否者可能会无法反序列化成功。
[Serializable] //特性,当为某个类加了该特性后,这个类就标记为了可序列化的了。
public class Person : Animal
{
private Car _myCar;
public Car MyCar
{
get { return _myCar; }
set { _myCar = value; }
}
//[NonSerialized]//当前这个字段就不会被序列化了。
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
二进制序列化要求:
1.被序列化的对象的类型必须标记为可序列化的。
2.二进制序列化会把属性对应的字段序列化到文件中,所以最好类型中不要使用自动属性(编译器会自动生成字段),而要自己写属性与字段
3.当序列化一个对象的时候,这个对象本身以及的所有父类都必须标记为可序列化的。
4.类型中所有属性与字段的类型必须也标记为可序列化的。接口不需要。
5.通过[NonSerialized]把某个字段标记为不可序列化的。
Person person = new Person();
person.Name = "张三";
person.Age = 19;
person.Email = "zhangsan@yahoo.com";
person.MyCar = new Car() { Brand = "时风" };
//二进制序列化步骤:
//1.创建二进制序列化器
BinaryFormatter bf = new BinaryFormatter();
//我们希望将对象序列化到一个文件上,所以要创建一个文件流
using (FileStream fsWrite = File.OpenWrite("person.bin"))
{
//开始执行二进制序列化
bf.Serialize(fsWrite, person);
}
Console.WriteLine("序列化完毕!");
Console.ReadKey();
反序列化的时候,需要创建原来被序列化的类型的对象,所以反序列化的时候需要引用被序列化的类型的对象。正是因为如此,所以在二进制序列化的时候,那些属性名、方法等根本不需要序列化,只需要把那些状态信息(数据→字段的值)序列化了就好了,对于那些方法等信息,在反序列化时,创建对象的时候会自动创建,然后根据序列化文件中的字段的值,进行赋值。
c#基础语言编程-序列化的更多相关文章
- c#基础语言编程-程序集和反射
程序集 什么是程序集? 1.程序集(assembly)是一个及一个以上托管模块,以及一些资源文件的逻辑组合. 2.程序集是组件复用,以及实施安全策略和版本策略的最小单位. 3.程序集是包含一个或者多个 ...
- c#基础语言编程-正则表达式应用
引言 在不同语言中虽正则表达式一样,但应用函数还是有所区别,在c#语言中使用Regex. 可以通过以下两种方式之一使用正则表达式引擎: 通过调用 Regex 类的静态方法. 方法参数包含输入字符串和正 ...
- c#基础语言编程-正则表达式基础
引言 正则表达式是一种用高度抽象的字符串来描述字符串特征,进而实现对字符串的匹配.提取.替换等等.正则表达式(以下简称正则,Regex)通常不独立存在,各种编程语言和工具作为宿主语言提供对正则的支持, ...
- c#基础语言编程-文件流操作
引言 在System.IO 命名空间下提供了一系列的类,我们可以通过相应的类进行文件.目录.数据流的操作. 1.File类:提供用于创建.复制.删除.移动和打开文件的静态方法.File类 2.File ...
- c#基础语言编程-编码
字符编码是计算机技术的基础理论,其字符编码有ASCII码.UTF-8.还有就是GB2312,当然这是在中国常用的. 1.ASCII码 在计算机内部所有的信息都是以二进制字符进行存储.用每个二进制位中的 ...
- c#基础语言编程-Path和Directory
引言 在程序常会对文件操作,在对文件操作中需要对文件路径的进行定位,在.Net中针对寻找文件提供两个静态类以供调用,Path和Directory. Path类 来自命名空间SYstem.IO,Path ...
- c#基础语言编程-装箱和拆箱
引言 为什么有装箱和拆箱,两者起到什么作用?NET的所有类型都是由基类System.Object继承过来的,包括最常用的基础类型:int, byte, short,bool等等,就是说所有的事物都是对 ...
- c#基础语言编程-多态
语言中的多态性是为了使程序有扩展性,为实现多态性,在程序中体现为接口.抽象类.父类.具体类. 接口就是一种规范,解决了多重继承的问题,类似一种规范,告诉我要做什么,具有什么能力,在接口中定义写行为属性 ...
- c#基础语言编程-集合
引言 在c#常用的集合分为非泛型集合和泛型集合. 非泛型集合的类和接口位于System.Collections命名空间.这些接口和类定义各种对象(如列表.队列.位数组.哈希表和字典)的集合. 泛型集合 ...
随机推荐
- Qt中,当QDockWidget的父窗口是一个不可以拖动的QTabWidget的时候实现拖动的方法
之前在做有关QDockWidget的内容时候遇到了瓶颈,那就是窗口弹出来之后拖动不了,也不可以放大和缩小,若是弹出来之后设置成了window的flags,也不可以拖动,而且也不是需要的效果. 1.弹出 ...
- (转)应用内存优化之OnLowMemory&OnTrimMemory
1.应用内存onLowMemory& onTrimMemory优化 onLowMemory& onTrimMemory简介:OnLowMemory是Android提供的API,在系统内 ...
- 为什么我们需要使用 touch 命令
为什么我们需要使用 touch 命令 既然 touch 命令描述的是改变时间戳,那么我们可能会想为什么我们需要去改变时间戳呢?这个问题会引发我们的深思.然而,我想有个理由可以解释为什么我们需要使用它. ...
- Jquery 和 Js
jQuery [一] jQuery 1: javaScript和 javaScript库: (1) javaScript自身存在的3个弊端:复杂的文档对象模型(DOM),不 ...
- InstallShield自定义图片资源
DialogSetInfo ( nInfoType, szInfoString, nParameter ); nInfoType: DLG_INFO_ALTIMAGE-Specifies an a ...
- union 与struct的空间计算
一.x86 总体上遵循两个原则: 整体空间----占用空间最大的成员(的类型)所占字节数的整数倍 对齐原则----内存按结构成员的先后顺序排列,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类 ...
- 运行从别处复制过来的linux可执行程序
1, 首先ldd看看缺不缺so文件,如果不缺可忽略下面的文字,直接执行 2, 先看看缺的这些库在系统上有没有,这些库可通过安装开发包,第三方软件进行安装 3, 找到可能会包含这些库的可执行程序,ldd ...
- 数据结构练习 01-复杂度2. Maximum Subsequence Sum (25)
Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to be { Ni, ...
- 第一个deeplearning4jproject跑起
deeplearning4j是基于java的深度学习库,当然,它有许多特点,但暂时还没学那么深入,所以就不做介绍了 需要学习dl4j,无从下手,就想着先看看官网的examples,于是,下载了exam ...
- bzoj 1040: [ZJOI2008]骑士 環套樹DP
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1755 Solved: 690[Submit][Status] ...