序列化又称串行化,是.NET运行时环境用来支持用户定义类型的流化的机制。其目的是以某种存储形成使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。
.NET框架提供了两种种串行化的方式:1、是使用BinaryFormatter进行串行化;2、使用XmlSerializer进行串行化。第一种方式提供了一个简单的二进制数据流以及某些附加的类型信息,而第二种将数据流格式化为XML存储。 可以使用[Serializable]属性将类标志为可序列化的。如果某个类的元素不想被序列化,1、可以使用[NonSerialized]属性来标志,2、可以使用[XmlIgnore]来标志。
序列化意思指的是把对象的当前状态进行持久化,一个对象的状态在面向对象的程序中是由属性表示的,所以序列化类的时候是从属性读取值以某种格式保存下来,而类的成员函数不会被序列化,.net存在几种默认提供的序列化,二进制序列化,xml和json序列化会序列化所有的实例共有属性。
-
using UnityEngine;
-
using System;
-
using System.Collections;
-
using System.IO;
-
using System.Collections.Generic;
-
using System.Runtime.Serialization.Formatters.Binary;
-
-
[ // 表示该类可以被序列化]
-
class Person
-
{
-
private string name;
-
[ // 表示下面这个age字段不进行序列化]
-
private int age;
-
public string Name
-
{
-
get { return name;}
-
set { name = value;}
-
}
-
public int Age
-
{
-
get { return age;}
-
set { age = value;}
-
}
-
public Person() { }
-
public Person(string name, int age)
-
{
-
this.name = name;
-
this.age = age;
-
}
-
-
public void SayHi()
-
{
-
Debug.LogFormat ( "我是{0}, 今年{1}岁", name, age);
-
}
-
}
-
-
-
public class BinarySerializer : MonoBehaviour {
-
-
string filePath = Directory.GetCurrentDirectory() + "/binaryFile.txt";
-
-
// Use this for initialization
-
void Start () {
-
List<Person> listPers = new List<Person> ();
-
Person per1 = new Person ( "张三", 18);
-
Person per2 = new Person ( "李四", 20);
-
listPers.Add (per1);
-
listPers.Add (per2);
-
SerializeMethod (listPers); // 序列化
-
DeserializeMethod(); // 反序列化
-
Debug.Log( "Done ! ");
-
}
-
-
void DeserializeMethod() // 二进制反序列化
-
{
-
FileStream fs = new FileStream (filePath, FileMode.Open);
-
BinaryFormatter bf = new BinaryFormatter ();
-
List<Person> list = bf.Deserialize (fs) as List<Person>;
-
-
if (list != null)
-
{
-
for ( int i = 0; i < list.Count; i++)
-
{
-
list [i].SayHi ();
-
}
-
}
-
fs.Close ();
-
}
-
-
void SerializeMethod(List<Person> listPers) // 二进制序列化
-
{
-
FileStream fs = new FileStream (filePath, FileMode.Create);
-
BinaryFormatter bf = new BinaryFormatter ();
-
bf.Serialize (fs, listPers);
-
fs.Close ();
-
}
-
-
// Update is called once per frame
-
void Update () {
-
-
}
-
}
序列化的文本打开后,内容如下所示:
反序列化输出结果:
大家好,我是张三,今年0岁
大家好,我是李四,今年0岁
由此看出,未序列化的字段存储的值为空
使用XmlSerializer进行串行化
关于格式化器还有一个问题,假设我们需要XML,有两中方案:要么编写一个实现IFormatter接口的类,采用的方式类似于SoapFormatter类,但是没有你不需要的信息;要么使用库类XmlSerializer,这个类不使用Serializable属性,但是它提供了类似的功能。
如果我们不想使用主流的串行化机制,而想使用XmlSeralizer进行串行化我们需要做一下修改:
a.添加System.Xml.Serialization命名空间。
b.Serializable和NoSerialized属性将被忽略,而是使用XmlIgnore属性,它的行为与NoSerialized类似。
c.XmlSeralizer要求类有个默认的构造器,这个条件可能已经满足了。
序列化:
XmlSerializer xs = new XmlSerializer(typeof(List<Peoson>));
xs.Serialize(fs, listPers);
反序列化:
XmlSerializer xs = new XmlSerializer(typeof(List<Peoson>));
List<Peoson> list = xs.Deserialize(fs) as List<Peoson>;
-
using UnityEngine;
-
using System;
-
using System.Collections;
-
using System.IO;
-
using System.Xml.Serialization;
-
using System.Xml;
-
using System.Collections.Generic;
-
-
[ // 表示该类可以被序列化]
-
[ // 设置为XML中的根元素名称]
-
public class Person
-
{
-
private string name;
-
private int age;
-
-
// [XmlElement("abc")]
-
public int abc = 1000; // 类的public属性字段都可以被序列化
-
-
// [XmlAttribute("Name")] 设置作为xml中的属性
-
public string Name
-
{
-
get { return name;}
-
set { name = value;}
-
}
-
// [XmlElement("Age")] 设置作为XML中的元素(默认状态)
-
public int Age
-
{
-
get { return age;}
-
set { age = value;}
-
}
-
public Person() { }
-
public Person(string name, int age)
-
{
-
this.name = name;
-
this.age = age;
-
}
-
-
public void SayHi()
-
{
-
Debug.LogFormat ( "我是{0}, 今年{1}岁", name, age);
-
}
-
}
-
-
-
public class XmlSerialize : MonoBehaviour {
-
-
string filePath = Directory.GetCurrentDirectory() + "/XmlFile.txt";
-
string filePath2 = Directory.GetCurrentDirectory() + "/XmlClassFile.txt";
-
-
// Use this for initialization
-
void Start () {
-
List<Person> listPers = new List<Person> ();
-
Person per1 = new Person ( "张三", 18);
-
Person per2 = new Person ( "李四", 20);
-
listPers.Add (per1);
-
listPers.Add (per2);
-
SerializeMethod (listPers); // 序列化
-
DeserializeMethod(); // 反序列化
-
-
// SerializeClassMethod (per1);
-
// DeserializeClassMethod ();
-
Debug.Log( "Done ! ");
-
}
-
-
void DeserializeClassMethod() // Xml实体类反序列化
-
{
-
FileStream fs = new FileStream (filePath, FileMode.Open);
-
XmlSerializer xs = new XmlSerializer( typeof(Person));
-
Person p = xs.Deserialize (fs) as Person;
-
if (p != null)
-
{
-
p.SayHi ();
-
}
-
fs.Close ();
-
}
-
-
-
void SerializeClassMethod(Person p) // Xml实体类序列化
-
{
-
FileStream fs = new FileStream (filePath2, FileMode.Create);
-
XmlSerializer xs = new XmlSerializer( typeof(Person));
-
xs.Serialize(fs, p);
-
fs.Close ();
-
}
-
-
-
void DeserializeMethod() // Xml列表反序列化
-
{
-
FileStream fs = new FileStream (filePath, FileMode.Open);
-
XmlSerializer xs = new XmlSerializer( typeof(List<Person>));
-
List<Person> listPers = xs.Deserialize (fs) as List<Person>;
-
if (listPers != null)
-
{
-
for ( int i = 0; i < listPers.Count; i++)
-
{
-
listPers [i].SayHi ();
-
}
-
}
-
fs.Close ();
-
}
-
-
void SerializeMethod(List<Person> listPers) // Xml列表序列化
-
{
-
FileStream fs = new FileStream (filePath, FileMode.Create);
-
XmlSerializer xs = new XmlSerializer( typeof(List<Person>));
-
xs.Serialize(fs, listPers);
-
fs.Close ();
-
}
-
-
// Update is called once per frame
-
void Update () {
-
-
}
-
}
Xml列表序列化的内容:
Xml实体类序列化的内容: