C#三十一 序列化与反序列化

简介: C#三十一 序列化与反序列化

   序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。

   .NET框架提供了两种串行化的方式:1、是使用BinaryFormatter进行串行化;2、使用SoapFormatter进行串行化;3、使用XmlSerializer进行串行化。第一种方式提供了一个简单的二进制数据流以及某些附加的类型信息,而第二种将数据流格式化为XML存储;第三种其实和第二种差不多也是XML的格式存储,只不过比第二种的XML格式要简化很多(去掉了SOAP特有的额外信息)。

   可以使用[Serializable]属性将类标志为可序列化的。如果某个类的元素不想被序列化,1、2可以使用[NonSerialized]属性来标志,2、可以使用[XmlIgnore]来标志。


重点:

Ø      理解序列化 / 反序列化概念

Ø      能够使用序列化/反序列化保持和恢复对象状态

预习功课:

Ø      序列化的概念

Ø      反序列化的概念

Ø      如何使用序列化和反序列化保持和恢复对象状态

Ø      如何利用序列化来操作Xml文件

8.1 序列化和反序列化简介

       C#序列化和反序列化,两者的程序处理方式基本一致,都是基于工厂模式的,所谓C#序列化就是是将对象转换为容易传输的格式的过程,一般情况下转化打流文件,放入内存或者IO文件中。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象,或者和其它应用程序共享使用。相反的,反序列化根据流重新构造对象。.NET自带的有两种序列化对象的方式,Xml和binary的,XML 序列化不转换方法、索引器、私有字段或只读属性(只读集合除外)。要序列化对象的所有字段和属性(公共的和私有的),请使用 BinaryFormatter,而不要使用 XML 序列化。


8.1.1 C#序列化和反序列化的实例应用剖析:

二进制的C#序列化的方式:


例如我们有个对对象:

1.            [Serializable]public class ClassToSerialize{ 
2.            public int id=100; 
3.            public string name="Name";  
4.            }  

需要序列化该对象,必须在给该类加上Serializable的属性,然后创建一个序列化写入的流:FileStream fileStream = new FileStream("temp.dat",FileMode.Create);然后创建二进制格式器:BinaryFormatter b=newBinaryFormatter();然后是序列化:b.Serialize(fileStream,c);,然后关闭保存流。(可以见下面的例子)


读取一个已经被序列化的对象的时候:操作方式一样,只是

5.           FileStream fileStream = new FileStream(  
6.           "temp.dat", FileMode.Open,  
7.           FileAccess.Read, FileShare.Read);  
8.           ClassToSerialize c =  
9.           (ClassToSerialize)b.Deserialize(fileStream); 
然后就可以读取了,完整的例子是:
10.       using System;  
11.       using System.IO;  
12.       using System.Runtime.Serialization;  
13.       using System.Runtime.Serialization.Formatters.Binary;  
14.       public class SerialTest{  
15.       public void SerializeNow(){  
16.       ClassToSerialize c=new ClassToSerialize();  
17.       FileStream fileStream = new FileStream(  
18.       "temp.dat", FileMode.Create); 
19.        
20.       BinaryFormatter b=new BinaryFormatter();  
21.       b.Serialize(fileStream,c);  
22.       fileStream.Close();  
23.       }  
24.       public void DeSerializeNow(){  
25.       ClassToSerialize c=new ClassToSerialize();  
26.       FileStream fileStream = new FileStream(  
27.       "temp.dat", FileMode.Open, 
28.        FileAccess.Read,  
29.        FileShare.Read);  
30.       BinaryFormatter b=new BinaryFormatter();  
31.       //SoapFormatter 
32.       c=(ClassToSerialize)b.Deserialize(fileStream);  
33.       Console.WriteLine(c.name);  
34.       fileStream.Close();  
35.       }  
36.       public static void Main(string[] s){  
37.       SerialTest st=new SerialTest();  
38.       st.SerializeNow();  
39.       st.DeSerializeNow();  
40.       }  
41.       }  
42.       [Serializable]  
43.       public class ClassToSerialize{  
44.       public int id=100;  
45.       public string name="Name";  
46.       }  

这就是自带的序列化和反序列的操作,但是,很多情况下,一个对象比较大,而且很多私有的属性和方法我们不需要,例如在原型模式里面序列化的话,只需要序列Clone方法和一些属性,私有的方法无需要,还例如在读取大规模的IO的时候,读取操作完全不需要... 这时候就需要自己集成重写序列的ISerializable接口:


实现该接口需要两个注意的,一个就是构造函数,主要是为了反序列,另一个就是GetObjectData,主要是执行序列化,例如我们现在有一个Employee类需要序列化


47.       [Serializable()]  


48.       //Set this attribute to all the classes that want to serialize


49.       public class Employee : ISerializable  


50.       //derive your class from ISerializable {


51.       public int EmpId;  


52.       public string EmpName;  


53.       [NonSerialized()]  


54.       public string NoSerialString="NoSerialString-Test";  


55.        


56.       }


需要注意的是我这里的NoSerialString属性前面有[NonSerialized()],就是说默认并不序列化这个属性,而是使用默认值。


首先是构造函数:

57.       public Employee(SerializationInfo info, StreamingContext ctxt) 
58.       {  
59.       EmpId = (int)info.GetValue(  
60.       "EmployeeId", typeof(int));  
61.       EmpName = (String)info.GetValue(  
62.       "EmployeeName", typeof(string));  
63.       //NoSerialString =  
64.       //(String)info.GetValue("NoSerialString", typeof(string)); 
65.       } 
然后是C#序列化方法,就是当写入流的时候怎么保存的:
66.       public void GetObjectData(SerializationInfo info, StreamingContext ctxt) {  
67.        
68.       info.AddValue("EmployeeId", EmpId);  
69.       info.AddValue("EmployeeName", EmpName);  
70.       } 
把上面两个方法写入到Employee类,然后写个测试的程序:
71.       public class ObjSerial{  
72.       public static void Main(String[] args){  
73.       Employee mp = new Employee();  
74.       mp.EmpId = 10;  
75.       mp.EmpName = "Omkumar";  
76.       mp.NoSerialString = "你好啊";  
77.        
78.          //C#序列化和反序列化之序列化 
79.       Stream stream = File.Open("EmployeeInfo.osl", FileMode.Create); 
80.       BinaryFormatter bformatter = new BinaryFormatter(); 
81.        
82.       Console.WriteLine("Writing Employee Information");  
83.       bformatter.Serialize(stream, mp);  
84.       stream.Close();  
85.        
86.        
87.       mp = null;  
88.          //C#序列化和反序列化之反序列 
89.       stream = File.Open("EmployeeInfo.osl", FileMode.Open); 
90.       bformatter = new BinaryFormatter();  
91.        
92.       Console.WriteLine("Reading Employee Information");  
93.       mp = (Employee)bformatter.Deserialize(stream);  
94.       stream.Close();  
95.        
96.       Console.WriteLine(  
97.       "Employee Id: {0}",mp.EmpId.ToString()); 
98.       Console.WriteLine(  
99.       "Employee Name: {0}",mp.EmpName);  
100.     Console.WriteLine( 
101.     "Employee NoSerialString: {0}",mp.NoSerialString); 
102.      
103.     }  
104.     }  

C#序列化和反序列化程序执行的结果是:


105.     Writing Employee Information


106.     Reading Employee Information


107.     Employee Id: 10


108.     Employee Name: Omkumar


109.     Employee NoSerialString: NoSerialString-Test


看到Employee NoSerialString:属性的值没有,它保持默认值,没有序列化。


8.2 Xml格式序列化及反序列化


要序列化的对象的类:


[Serializable]
  public class Person
  {
  private string name;
  public string Name
  {
  get
  {
      return name;
  }
  set
  {
      name=value;
  }
  }
  public string Sex;
  public int Age=31;
  public Course[] Courses;
  public Person()
  {
  }
  public Person(string Name)
  {
      name=Name;
      Sex="男";
  }
  }
  [Serializable]
  public class Course
  {
  public string Name;
  [XmlIgnore]public string Description;
  public Course()
  {
  }
  public Course(string name,string description)
  {
      Name=name;
      Description=description;
  }
  }
  进行序列化及反序列化的测试类:
  class Test
  {
  //序列化
  public void Serialiaze()
  {
      Person c=new Person("cyj")
      c.Courses=new Course[2];
      c.Courses[0]=new Course("英语","交流工具")
      c.Courses[1]=new Course("数学","自然科学")
      XmlSerializer xs=new XmlSerializer(typeof(Person));
      Stream stream = newFileStream("c:\\cyj.xml", FileMode.Create,             FileAccess.Write,FileShare.ReadWrite);
      xs.Serialize(stream, c);
      stream.Close();
  }
  //反序列化
  public void Deserialize()
  {
      XmlSerializer xs=new XmlSerializer(typeof(Person));
      Stream stream = newFileStream("c:\\cyj.xml", FileMode.Open, FileAccess.Read,FileShare.ReadWrite);
      Person p=(Person)xs.Deserialize(stream);
      Console.WriteLine(p.Name);
      Console.WriteLine(p.Age.ToString());
      Console.WriteLine(p.Courses.Length.ToString());
      Console.Read();
  }
  }

格式化后Xml的文档内容为:


<?xml version="1.0"?>
  <Person xmlns:xsd=http://www.w3.org/2001/XMLSchemaxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Sex>男</Sex>
   <Age>31</Age>
   <Courses>
   <Course>
      <Name>英语</Name>
   </Course>
   <Course>
      <Name>数学</Name>
   </Course>
   </Courses>
      <Name>cyj</Name>
  </Person>

 视频课堂https://edu.csdn.net/course/play/7621


目录
相关文章
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
5月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
278 1
|
5月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
298 1
|
9月前
|
存储 Java 编译器
说一说关于序列化/反序列化中的细节问题
我是小假 期待与你的下一次相遇 ~
172 1
|
9月前
|
JSON Java 数据库连接
|
10月前
|
存储 安全 IDE
说一说序列化与反序列化中存在的问题
本文详细解析了Java中的序列化机制,包括序列化的概念、实现方式及应用场景。通过Student类的实例演示了对象的序列化与反序列化过程,并分析了`Serializable`接口的作用以及`serialVersionUID`的重要意义。此外,文章还探讨了如何通过自定义`readObject()`方法增强序列化的安全性,以及解决可序列化单例模式中可能产生的多实例问题。最后提供了代码示例和运行结果,帮助读者深入理解序列化的原理与实践技巧。
256 2
|
10月前
|
JSON JavaScript 前端开发
Go语言JSON 序列化与反序列化 -《Go语言实战指南》
本文介绍了 Go 语言中使用 `encoding/json` 包实现 JSON 与数据结构之间的转换。内容涵盖序列化(`Marshal`)和反序列化(`Unmarshal`),包括基本示例、结构体字段标签的使用、控制字段行为的标签(如 `omitempty` 和 `-`)、处理 `map` 和切片、嵌套结构体序列化、反序列化未知结构(使用 `map[string]interface{}`)以及 JSON 数组的解析。最后通过表格总结了序列化与反序列化的方法及类型要求,帮助开发者快速掌握 JSON 数据处理技巧。
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
697 1
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。

热门文章

最新文章