C#关于序列化和反序列化

C#关于序列化和反序列化,第1张

工具/原料

Visual Studio(本文使用VS2013,其他版本亦可)。

准备工作和类设计

1

启动VS,新建C# 类库项目,并命名为KTools。

2

添加C# Winform项目,命名为Test,重命名主窗口为MainForm,并设置为启动项。同时在KTools项目添加文件夹Serializer,并在该文件夹拍带中添加3个类:XMLSerializer、SoapSerializer和BinarySerializer,如下图:

3

该类库的设计目标是快速方便,最好把序列和反序列化的方法做成静态方法,这样就可以省去了实例化的步骤。序列化大体上分为序列化到文件和序列化到流,虽然序列化到流更为通用,但序列化到流的步骤中似乎没有什么可简化的,故我们只讨论序列化到文件。对于序列化到旅贺慧文件,我们需要考虑文件是否存在、写入是否覆盖等,为了方便使用只考虑“存在覆盖”的原则。为了尽可能的避免异常(因为这样使用起来更简单,不必考虑拆答是否会引发异常),我们必须确保对象可序列化、文件存在、反序列化时文件不空等。另外,为了避免反序列化时的类型转化,以及更好的使用类,把序列化和范序列化的方法做成泛型。

END

XML序列化和反序列化

1

XML序列化需要引用名称空间System.Xml.Serialization,序列化代码如下:

public static void Serialize<T>(T o, string filePath)

{

try

{

XmlSerializer formatter = new XmlSerializer(typeof(T))

StreamWriter sw = new StreamWriter(filePath, false)

formatter.Serialize(sw, o)

sw.Flush()

sw.Close()

}

catch (Exception) { }

}

2

XML反序列化,代码如下:

public static T DeSerialize<T>(string filePath)

{

try

{

XmlSerializer formatter = new XmlSerializer(typeof(T))

StreamReader sr = new StreamReader(filePath)

T o = (T)formatter.Deserialize(sr)

sr.Close()

return o

}

catch (Exception)

{

}

return default(T)

}

END

Soap序列化

1

Soap序列化需要名称引用空间System.Runtime.Serialization.Formatters.Soap,并且该dll引用需要手工添加。Soap序列化代码,如下:

public static void Serialize<T>(T o, string filePath)

{

try

{

SoapFormatter formatter = new SoapFormatter()

// StreamWriter sw = new StreamWriter(filePath, false)

Stream stream = new FileStream(filePath , FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)

formatter.Serialize(stream, o)

stream.Flush()

stream.Close()

}

catch (Exception) { }

}

2

Soap反序列化,代码如下:

public static T DeSerialize<T>(string filePath)

{

try

{

SoapFormatter formatter = new SoapFormatter()

// StreamReader sr = new StreamReader(filePath)

Stream destream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)

T o = (T)formatter.Deserialize(destream)

destream.Flush()

destream.Close()

return o

}

catch (Exception)

{

}

return default(T)

}

END

Binary序列化和反序列化

1

Binary序列化,代码:

public static void Serialize<T>(T o, string filePath)

{

try

{

BinaryFormatter formatter = new BinaryFormatter()

Stream stream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)

formatter.Serialize(stream, o)

stream.Flush()

stream.Close()

}

catch (Exception) { }

}

2

Binary反序列化,代码:

public static T DeSerialize<T>(string filePath)

{

try

{

BinaryFormatter formatter = new BinaryFormatter()

Stream destream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)

T o = (T)formatter.Deserialize(destream)

destream.Flush()

destream.Close()

return o

}

catch (Exception)

{

}

return default(T)

}

END

测试

在Test项目中的MainForm窗体中添加两个Button控件,分别命名为“序列化”和“反序列化”,并添加代码:

public partial class MainForm : Form

{

public MainForm()

{

InitializeComponent()

}

private void button1_Click(object sender, EventArgs e)

{

string str = "Hello world!!!"

KTools.Serializer.XMLSerializer.Serialize<string>(str, "1.txt")

MessageBox.Show("序列化完毕")

}

private void button2_Click(object sender, EventArgs e)

{

string str = KTools.Serializer.XMLSerializer.DeSerialize<string>("1.txt")

MessageBox.Show(str)

}

}

调试运行,查看结果:

把对象转换为字节序列的过程称为对象的序列化

把字节序列恢复为对象的过程称为对象的反序列化

对象的序列化主要有两种用途:

1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

2) 在网络上传送对象的字节序列。

在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存。比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。

java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化誉激为一个对象,并将其返回。

只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。

对象序列化包括如下步骤:

1) 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;

2) 通过对象输出流的writeObject()方法写对象。

对象反序列化的步骤如下:

1) 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

2) 通过对象输入流的readObject()方法读取对象。

输出如下

输出如下

在序列化时显示指定serialVersionUID作为版本号,凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量,如果不显示指定,jvm会隐式给我们随机生成一个serialVersionUID,这个serialVersionUID是根据对象的信息生成的,如果我们对序列化对象有所改动的话,serialVersionUID也会随之改动,再反序列化就会因serialVersionUID不一致而报错、

示例:

序列化和反序列化跟上面敬虚如一样

反序列化

此时是正常且成功的,但是,我们如果现在在User对象新增一个属性

上面我说,serialVersionUID是根据对象信息生成的,现在对象多了一个属性,信息已经改变,再次生成的serialVersionUID 已经和刚才的不一样了,这时我们再进亮启行反序列化会报如下错误

我们指定serialVersionUID后就可以随意修改了

 猛手 序列化(Serialization)是将对象的状态信息转换为可以存顷枯储或传输的形式的过程。而反序列化是从序列化的表示形式中提取数据,并直接设置对象状态,但与可访问性规则无关。

脚本是批处理文件的延伸,是一种纯文本保存的程序,一般来说的计算机脚本程序是确定的一系列控制计算机进行运算 *** 作动作枝乎嫌的组合,在其中可以实现一定的逻辑分支等。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/12208358.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存