你的位置:首页 > ASP.net教程

[ASP.net教程]C#序列化与反序列化学习


最近为了换一份新工作,准备了不少笔试题。从笔试当中自己发现了不少基础知识的盲点。很庆幸这样的机会,可以让自己对于基础知识的理解又上升一个台阶。此文介绍C#里面的序列化与反序列化的知识,如果你是大鸟,请口下留情。

首先,什么是序列化与反序列化呢?

序列化就是将对象的状态信息转换为可以存储或传输形式的过程。其实就是将对象持久化,比如说把对象保存为二进制或者是

 

那么,运用序列化的好处又是什么呢?

(1)以某种存储形式(二进制或者是

(2)使对象的传递更加容易,比如你用ajax向服务器请求信息,服务器可以直接将model对象通过序列化来输出json字符串,也可以通过反序列化将你传过去的json字符串组装成对象,就免去了拼字符串和解析字符串的过程。

最后,在.Net里面怎么实现序列化技术?

(1)二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同的应用程序之间共享对象。您可以将对象序列化到流、磁盘、内存和网络等等。

(2) 以上内容摘自百科的内容与百度的内容.

关于这两点的概念,我自己也不大明白是什么意思?

保持类型保真度,一开始我是认为是成员变量的类型,以为用

 

1#针对二进制序列化与反序列化,.Net是使用BinaryFormatter对象来进行序列化与反序列化。

一般的实现方法,是把可序列化的类用特征类[Serializable]来标志,当然,不想序列类的成员,可以用[NonSerialized]特征类来标志。类里面的所有成员变量都能被序列化。然后实例化命名空间System.Runtime.Serialization.Formatters.Binary下的BinaryFormatter对象,借助其Serialize方法来实现序列化与Deserialize方法来实现反序列化。

复制代码
using System;using System.IO;using System.Collections;using System.Runtime.Serialization.Formatters.Binary;using System.Runtime.Serialization;[Serializable]public class SerializeObject{  public int ID  {    get;    set;  }  public string UserName  {    get;    set;  }  public string Password  {    get;    set;  }  [NonSerialized]  public string notSerialize;}public class App{  [STAThread]  static void Main()  {    Serialize();    Deserialize();  }  static void Serialize()  {    SerializeObject serializeObject = new SerializeObject();    serializeObject.ID = 1;    serializeObject.UserName = "csdbfans";    serializeObject.Password = "csdbfans";    serializeObject.notSerialize = "博客园";    FileStream fs = new FileStream("DataFile.dat", FileMode.Create);    BinaryFormatter formatter = new BinaryFormatter();    try    {      formatter.Serialize(fs, serializeObject);    }    catch (SerializationException e)    {      Console.WriteLine("Failed to serialize. Reason: " + e.Message);      throw;    }    finally    {      fs.Close();    }  }  static void Deserialize()  {    SerializeObject serializeObject = null;    FileStream fs = new FileStream("DataFile.dat", FileMode.Open);    try    {      BinaryFormatter formatter = new BinaryFormatter();      serializeObject = (SerializeObject)formatter.Deserialize(fs);    }    catch (SerializationException e)    {      Console.WriteLine("Failed to deserialize. Reason: " + e.Message);      throw;    }    finally    {      fs.Close();    }    Console.WriteLine("反序列Serializable的结果:ID->" + serializeObject.ID + ", UserName->"              
+ serializeObject.UserName + ", Password->" + serializeObject.Password); Console.WriteLine("反序列化NonSerialized结果:" + serializeObject.notSerialize); }}
复制代码

 结果为:


其实你如果进到DataFile.dat文件的话,你会发现用记事本,写字板来打开的话,都是会出现乱码。因为它是用二进制的方式来保存的,所以你只有是在用二进制的方式下才能看到里面的内容。不过对于我们来说,即使看到二进制的内容,我们也不大可能知道是什么意思。所以可能只有通过反序列化的方式来读出文档的内容。

2#针对

其一:使用类将对象序列化到

与第1点的区别,摘自寒江笠博文:

(I)不使用[Serializable]特征类与[NonSerializable]特征类,只使用特征类[System.] 来标志哪些成员变量不需要被序列化。

(II)不能序列化私有成员变量(不确定,因为我试过可以

(III)要求被序列化的类要有一个默认的构造函数(不确定,不知道这里的构造函数是为了什么而需要的

复制代码
using System;using System.IO;using System.Collections;using System.using System.Runtime.Serialization;public class SerializeObject{  public int ID  {    get;    set;  }  public string UserName  {    get;    set;  }  public string Password  {    get;    set;  }  [public string notSerialize;}public class App{  [STAThread]  static void Main()  {    Serialize();    Deserialize();  }  static void Serialize()  {    SerializeObject serializeObject = new SerializeObject();    serializeObject.ID = 1;    serializeObject.UserName = "csdbfans";    serializeObject.Password = "csdbfans";    serializeObject.notSerialize = "博客园";    FileStream fs = new FileStream("DataFile.", FileMode.Create);    = new typeof(SerializeObject));    try    {      formatter.Serialize(fs, serializeObject);    }    catch (SerializationException e)    {      Console.WriteLine("Failed to serialize. Reason: " + e.Message);      throw;    }    finally    {      fs.Close();    }  }  static void Deserialize()  {    SerializeObject serializeObject = null;    FileStream fs = new FileStream("DataFile.", FileMode.Open);    try    {      = new typeof(SerializeObject));      serializeObject = (SerializeObject)formatter.Deserialize(fs);    }    catch (SerializationException e)    {      Console.WriteLine("Failed to deserialize. Reason: " + e.Message);      throw;    }    finally    {      fs.Close();    }    Console.WriteLine("反序列Serializable的结果:ID->" + serializeObject.ID + ", UserName->"              
+ serializeObject.UserName + ", Password->" + serializeObject.Password); Console.WriteLine("反序列化NonSerialized结果:" + serializeObject.notSerialize); }}
复制代码

结果:




 其二:使用SoapFormatter类将对象序列化到

同样是序列化到

SoapFormatter 和 BinaryFormatter 两个类实现 IRemotingFormatter 接口以支持远程过程调用 (RPC),实现 IFormatter 接口(由 IRemotingFormatter 继承)以支持对象图形的序列化。SoapFormatter 类还支持对 ISoapMessage 对象进行 RPC,而不必使用 IRemotingFormatter 功能。此概念来自MSDN文档,有兴趣请点击去研读详细内容。

其二的方法跟第一点(1#)的实现方法基本一样,毕竟都是实现相同的接口,有一定的共性,只是最终存储的格式或者是传输的方式不一样。

复制代码
using System;using System.IO;using System.Collections;using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Soap;[Serializable]public class SerializeObject{  public int ID  {    get;    set;  }  public string UserName  {    get;    set;  }  public string Password  {    get;    set;  }  [NonSerialized]  public string notSerialize;}public class App{  [STAThread]  static void Main()  {    Serialize();    Deserialize();  }  static void Serialize()  {    SerializeObject serializeObject = new SerializeObject();    serializeObject.ID = 1;    serializeObject.UserName = "csdbfans";    serializeObject.Password = "csdbfans";    serializeObject.notSerialize = "博客园";    FileStream fs = new FileStream("DataFile.soap", FileMode.Create);    SoapFormatter formatter = new SoapFormatter();    try    {      formatter.Serialize(fs, serializeObject);    }    catch (SerializationException e)    {      Console.WriteLine("Failed to serialize. Reason: " + e.Message);      throw;    }    finally    {      fs.Close();    }  }  static void Deserialize()  {    SerializeObject serializeObject = null;    FileStream fs = new FileStream("DataFile.soap", FileMode.Open);    try    {      SoapFormatter formatter = new SoapFormatter();      serializeObject = (SerializeObject)formatter.Deserialize(fs);    }    catch (SerializationException e)    {      Console.WriteLine("Failed to deserialize. Reason: " + e.Message);      throw;    }    finally    {      fs.Close();    }    Console.WriteLine("反序列Serializable的结果:ID->" + serializeObject.ID + ", UserName->"              
+ serializeObject.UserName + ", Password->" + serializeObject.Password); Console.WriteLine("反序列化NonSerialized结果:" + serializeObject.notSerialize); }}
复制代码

结果为: 

复制代码
<SOAP-ENV:Envelope //www.w3.org/2001/=http://www.w3.org/2001/-ENC=http://schemas.-ENV=http://schemas.=http://schemas.microsoft.com/soap/encoding/clr/1.0SOAP-ENV:encodingStyle="http://schemas."><SOAP-ENV:Body><a1:SerializeObject id="ref-1" "http://schemas.microsoft.com/clr/assem/MyTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull"><_x003C_ID_x003E_k__BackingField>1</_x003C_ID_x003E_k__BackingField><_x003C_UserName_x003E_k__BackingField id="ref-3">csdbfans</_x003C_UserName_x003E_k__BackingField><_x003C_Password_x003E_k__BackingField href="#ref-3"/></a1:SerializeObject></SOAP-ENV:Body></SOAP-ENV:Envelope>
复制代码

 

这里使用寒江笠博文来进行两种技术的对比:

二进制序列化的优点:

(1)所有的类成员变量(包括只读的)都可以被序列化

(2)性能非常好

(1)互操作性好

(2)不需要严格的二进制依赖

(3)可读性强

这是我学习序列化与反序列化的一个过程,文中引用了不少“前人”的结果,但是文中还是有些内容不是很懂,希望还是能给大家带来帮助,哪怕是一丁点,也足矣!如果你也喜欢,转载时,请标明出处,谢谢!