C#序列化与反序列化
我们经常需要将对象的字段值保存到磁盘中,并在以后检索此数据。尽管不使用序列化也能完成这项工作,但这种方法通常很繁琐而且容易出错,并且在需要跟踪对象的层次结构时,会变得越来越复杂。可以想象一下编写包含大量对象的大型业务应用程序的情形,程序员不得不为每一个对象编写代码,以便将字段和属性保存至磁盘以及从磁盘还原这些字段和属性。序列化提供了轻松实现这个目标的快捷方法。
.NET公共语言运行时 (CLR) 管理对象在内存中的分布,.NET 框架则通过使用反射提供自动的序列化机制。对象序列化后,类的名称、程序集以及类实例的所有数据成员均被写入存储媒体中。对象通常用成员变量来存储对其他实例的引用。类序列化后,序列化引擎将跟踪所有已序列化的引用对象,以确保同一对象不被序列化多次。.NET 框架所提供的序列化体系结构可以自动正确处理对象图表和循环引用。对对象图表的唯一要求是,由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。
当反序列化已序列化的类时,将重新创建该类,并自动还原所有数据成员的值。
在C#中常见的序列化的方法主要也有三个:BinaryFormatter、SoapFormatter、XML序列化。本文就通过一个小例子主要说说这三种方法的具体使用和异同点。
新建一个vs2008控制台工程SerializableTest,添加一个Person类,加上[Serializable]使其可以被序列化
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
namespace operateXmlConifg
{
[Serializable]
public class Student
{
public Student() { }
public string stuName { get; set; }
public string sex { get; set; }
public int age { get; set; }
public string love { get; set; }
}
}
一、BinaryFormatter序列化方式
序列化和反序列化:将person保存到confing中,然后在从config文件中读取出来,通用的方法
{
public BFormatter() { }
/// <summary>
/// BinaryFormatter序列化方式
/// </summary>
/// <param name="filepath"></param>
/// <param name="obj"></param>
public static void save(string filepath,object obj)
{
IFormatter formatter = new BinaryFormatter();
Stream fs = null;
try
{
fs = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.Write);
formatter.Serialize(fs, obj);
}
catch (Exception e)
{
throw e;
}
finally
{
if(fs!=null)
{
fs.Close();
}
}
}
/// <summary>
/// BinaryFormatter反序列化方式
/// </summary>
/// <param name="filepath"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static object load(string filepath)
{
IFormatter formatter = new BinaryFormatter();
Stream fs = null;
try
{
fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
return formatter.Deserialize(fs);
}
catch (Exception e)
{
throw e;
}
finally
{
if (fs != null)
{
fs.Close();
}
}
}
然后在页面中,调用即可
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
namespace operateXmlConifg
{
public partial class BFormatter1 : System.Web.UI.Page
{
string xmlpath = "XmlConfig/stuBF.config";
protected void Page_Load(object sender, EventArgs e)
{
}
/// <summary>
/// BinaryFormatter序列化方式
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button1_Click(object sender, EventArgs e)
{
Student stu = new Student();
stu.stuName = "张三";
stu.sex = "男";
stu.age = 25;
stu.love = "唱歌,上网";
BFormatter.save(Server.MapPath(xmlpath), stu);//序列化
}
/// <summary>
/// BinaryFormatter反序列化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button2_Click(object sender, EventArgs e)
{
Student stu = (Student)BFormatter.load(Server.MapPath(xmlpath));
txtName.Text = stu.stuName;
txtSex.Text = stu.sex;
txtAge.Text = stu.age.ToString();
txtLove.Text = stu.love;
}
}
}
注意:反序列化还原对象时,并不会调用Person类的构造函数
二、SoapFormatter序列化方式
与BinaryFormatter序列化方式类似,只需要把IFormatter formatter = new BinaryFormatter()改成 IFormatter formatter = new SoapFormatter(),并且引用程序集System.Runtime.Serialization.Formatters.Soap.dll(.net自带的)
结果与第一种方式一样。
序列化之后的文件是Soap格式的文件(简单对象访问协议(Simple Object Access Protocol,SOAP),是一种轻量的、简单的、基于XML的协议,它被设计成在WEB上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议(HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用(RPC)等大量的应用程序。SOAP使用基于XML的数据结构和超文本传输协议(HTTP)的组合定义了一个标准的方法来使用Internet上各种不同操作环境中的分布式对象。),其内容如下:
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:Person id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/SerializableTest/SerializableTest%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<_x003C_Sno_x003E_k__BackingField id="ref-3">200719</_x003C_Sno_x003E_k__BackingField>
<_x003C_Name_x003E_k__BackingField id="ref-4">yuananyun</_x003C_Name_x003E_k__BackingField>
<_x003C_Sex_x003E_k__BackingField id="ref-5">man</_x003C_Sex_x003E_k__BackingField>
<_x003C_Age_x003E_k__BackingField>22</_x003C_Age_x003E_k__BackingField>
</a1:Person>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
三、XML序列化方式
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.IO;
using System.Xml.Serialization;
namespace operateXmlConifg
{
public class SerializationHelper
{
public SerializationHelper() { }
/// <summary>
/// 序列化
/// 注意:采用xml序列化的方式只能保存public的字段和可读写的属性,对于private等类型的字段不能进行序列化
/// </summary>
/// <param name="filePath"></param>
/// <param name="obj"></param>
public static void Save(string filePath, object obj)
{
FileStream fs = null;
try
{
//FileMode.Open:打开现有的文件
fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
XmlSerializer xs = new XmlSerializer(obj.GetType());
xs.Serialize(fs, obj);
}
catch (Exception e)
{
throw e;
}
finally
{
if (fs != null)
{
fs.Close();
}
}
}
/// <summary>
/// 反序列化
/// </summary>
/// <param name="type"></param>
/// <param name="filepath"></param>
/// <returns></returns>
public static object Load(Type type,string filepath)
{
FileStream fs = null;
try
{
fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read);
XmlSerializer xs = new XmlSerializer(type);
return xs.Deserialize(fs);
}
catch (Exception ex)
{
throw ex;
}
finally {
if(fs!=null)
{
fs.Close();
}
}
}
}
}
页面调用
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.IO;
using System.Xml.Serialization;
namespace operateXmlConifg
{
public partial class _Default : System.Web.UI.Page
{
string xmlpath = "XmlConfig/stu.config";
protected void Page_Load(object sender, EventArgs e)
{
}
/// <summary>
/// xml序列化方式
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button1_Click(object sender, EventArgs e)
{
Student stu = new Student();
stu.stuName = "张三";
stu.sex = "男";
stu.age = 25;
stu.love = "唱歌,上网";
SerializationHelper.Save(Server.MapPath(xmlpath), stu);//序列化
}
/// <summary>
/// xml反序列化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Button2_Click(object sender, EventArgs e)
{
Student stu = (Student)SerializationHelper.Load(typeof(Student), Server.MapPath(xmlpath));
txtName.Text = stu.stuName;
txtSex.Text = stu.sex;
txtAge.Text = stu.age.ToString();
txtLove.Text = stu.love;
}
}
}
格式:
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<stuName>张三</stuName>
<sex>男</sex>
<age>25</age>
<love>唱歌,上网</love>
</Student>
注意:采用xml序列化的方式只能保存public的字段和可读写的属性,对于private等类型的字段不能进行序列化
代码下载:序列化和反序列化