.net基础---序列化
概念:
对象在内存空间中,当程序以关闭,对象就会被CLR的垃圾回收机制销毁,程序再次运行的时候就又是一片新天地。
如果希望程序第二次运行时能"重现"第一次运行时的"场景",应用程序就必须采用某种方式讲对象的各个字段的值保存到磁盘文件中,这样在需要时可以从磁盘重重新获取对象中各个字段的值
将一个内存中的对象保存到流中,并在需要时可以从流中重新读取数据重建对象的过程为"对象的序列化"(Serialization)与"反序列化"(Deserialization)
对象序列化与流:
文件本身由一个个的二进制数0和1组成,8个二进制位(bit)构成一个字节(byte),字节是文件存取的最小单位,不管文件中存储的是什么数据,计算机都把他看成一个字节流。
存在于文件中的二进制数据是有序的,从文件开始到结束不能随意的更改其次序。在.NET中把文件本身看成一个数据的"小溪",用"文件流"这个概念来代表
.NET为流操作功能提供了若干个类,都放在了System.IO这个命名空间中,最常用的是用于存取文件流的FileStream和用于存取内存缓冲区的内存流"MemoryStream"
对象序列化,就是将对象数据写入流中,最常见的是写入到"FileStream"和"MemoryStream".
将对象数据保存到流的过程中,有两种保存数据的方式:一种是将对象的数据看成二进制的数据直接写入流中,称为"二进制序列化",另一种是将对象的数据用XML方式表示之后再以纯文本的方式写入流中称为"XML序列化"。.NET提供了两种数据格式化器(Formatter)来完成上述的两种数据转换工作
BinaryFormatter类为二进制序列化提供转换,SoapFormatter类为XML序列化提供转换
XML序列化可以使对象以一种平台无关的方式表达,很容易的再网上传送,实现对象的远程传输
XML序列化的确定是速度慢,生成的文件数量大,安全行不如二进制序列化
使用二进制序列化(BinaryFormatter)
1.简单对象的序列化
创建一个Student对象,要序列化的对象必须要用[Serializable]标记
1 [Serializable] 2 public class Student 3 { 4 string _name; 5 int _age; 6 public Student() { } 7 public Student(string name, int age) 8 { 9 _name = name; 10 _age = age; 11 } 12 public string Name 13 { 14 get { return _name; } 15 set { _name = value; } 16 } 17 18 public int Age 19 { 20 get { return _age; } 21 set { _age = value; } 22 } 23 }
用序列化的方法把Student对象信息保存到文件中
1 private void WriteFile(Student stu) 2 { 3 string fileName = ShowSaveFileDialog("学生信息","(*.ini)|*.ini"); 4 using (FileStream fs=new FileStream(fileName, FileMode.Create)) 5 { 6 IFormatter formatter = new BinaryFormatter(); 7 formatter.Serialize(fs, stu); 8 MessageBox.Show(string.Format("对象已保存在文件:{0}中",fileName)); 9 } 10 } 11 private string ShowSaveFileDialog(string path,string filter) 12 { 13 SaveFileDialog sfd = new SaveFileDialog(); 14 sfd.FileName = path; 15 sfd.Filter = filter; 16 if (sfd.ShowDialog() == DialogResult.OK) 17 return sfd.FileName; 18 return string.Empty; 19 }
读取文件中的Student信息
1 private Student ReadFile() 2 { 3 string fileName = ShowOpenFileDialog(); 4 using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate)) 5 { 6 IFormatter formatter = new BinaryFormatter(); 7 return formatter.Deserialize(fs) as Student; 8 } 9 } 10 private string ShowOpenFileDialog() 11 { 12 OpenFileDialog ofd = new OpenFileDialog(); 13 ofd.Filter = "(*.ini)|*.ini"; 14 if (ofd.ShowDialog() == DialogResult.OK) 15 return ofd.FileName; 16 return string.Empty; 17 }
实现的界面

2.控制序列化过程
在Student的原基础上增加显示"生日"和"年龄"字段,"年龄"这个字段依赖于"生日",要是时间有变化,"年龄"字段值始终不变是是不符合时间情况的。
要知道生日,用当前的时间一减,就可以得到年龄,所以可以选择不序列化"年龄"这个字段,而在反序列化的时候现场计算出这个值再赋值给student对象。
.NET提供了[NonSerialized]标记,来标记那些不允许序列化的字段,同时定义了"IDeserializationCallback"接口中的OnDeserialization()方法,可在反序列化完成时自动调用
1 [Serializable] 2 public class Student:IDeserializationCallback 3 { 4 string _name; 5 //Nonserialized只能标记字段,不能标记属性 6 [NonSerialized] 7 int _age; 8 DateTime _birthDay; 9 public Student() { } 10 public Student(string name, int age,DateTime birthDay) 11 { 12 _name = name; 13 _age = age; 14 _birthDay = birthDay; 15 } 16 public Student(string name, int age) 17 { 18 _name = name; 19 _age = age; 20 } 21 public string Name 22 { 23 get { return _name; } 24 set { _name = value; } 25 } 26 public int Age 27 { 28 get { return _age; } 29 set { _age = value; } 30 } 31 public DateTime BirthDay 32 { 33 get { return _birthDay; } 34 set { _birthDay = value; } 35 } 36 37 void IDeserializationCallback.OnDeserialization(object sender) 38 { 39 _age = DateTime.Now.Year - _birthDay.Year; 40 } 41 }
存的时候随便写一个年龄

创建的时候反序列化完成时计算年龄进行填写

3.利用序列化克隆:
详见对象克隆
浙公网安备 33010602011771号