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


目录
相关文章
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
3月前
|
存储 开发框架 .NET
解锁SqlSugar新境界:利用Serialize.Linq实现Lambda表达式灵活序列化与反序列化,赋能动态数据查询新高度!
【8月更文挑战第3天】随着软件开发复杂度提升,数据查询的灵活性变得至关重要。SqlSugar作为一款轻量级、高性能的.NET ORM框架,简化了数据库操作。但在需要跨服务共享查询逻辑时,直接传递Lambda表达式不可行。这时,Serialize.Linq库大显身手,能将Linq表达式序列化为字符串,实现在不同服务间传输查询逻辑。结合使用SqlSugar和Serialize.Linq,不仅能够保持代码清晰,还能实现复杂的动态查询逻辑,极大地增强了应用程序的灵活性和可扩展性。
124 2
|
8天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
21天前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
27天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。
|
8天前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
7 0
|
2月前
|
存储 XML JSON
用示例说明序列化和反序列化
用示例说明序列化和反序列化
|
2月前
|
JSON fastjson Java
niubility!即使JavaBean没有默认无参构造器,fastjson也可以反序列化。- - - - 阿里Fastjson反序列化源码分析
本文详细分析了 Fastjson 反序列化对象的源码(版本 fastjson-1.2.60),揭示了即使 JavaBean 沲有默认无参构造器,Fastjson 仍能正常反序列化的技术内幕。文章通过案例展示了 Fastjson 在不同构造器情况下的行为,并深入探讨了 `ParserConfig#getDeserializer` 方法的核心逻辑。此外,还介绍了 ASM 字节码技术的应用及其在反序列化过程中的角色。
65 10
|
2月前
|
存储 Java 开发者
Java编程中的对象序列化与反序列化
【9月更文挑战第20天】在本文中,我们将探索Java编程中的一个核心概念——对象序列化与反序列化。通过简单易懂的语言和直观的代码示例,你将学会如何将对象状态保存为字节流,以及如何从字节流恢复对象状态。这不仅有助于理解Java中的I/O机制,还能提升你的数据持久化能力。准备好让你的Java技能更上一层楼了吗?让我们开始吧!
|
2月前
|
存储 Java
Java编程中的对象序列化与反序列化
【9月更文挑战第12天】在Java的世界里,对象序列化与反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何通过实现Serializable接口来标记一个类的对象可以被序列化,并探索ObjectOutputStream和ObjectInputStream类的使用,以实现对象的写入和读取。我们还将讨论序列化过程中可能遇到的问题及其解决方案,确保你能够高效、安全地处理对象序列化。