简介
序列化:将对象保存到文件或数据库(虚的->实质)
反序列化:从文件数据中转化为原来对象(实质->虚的)
C#常见的序列化有三种:BinaryFormatter、SoapFormatter、XML
作用
- 进程下次启动读取上次保存的对象信息
- 不同进程间传递数据
要求
- public类型或者有[SerializeField]属性
- 不是static、const、readonly
- 类型必须是Unity可以序列化的类型
实例
-
BinaryFormatter
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Runtime.Serialization.Formatters.Binary; using System.IO; using System; public class Test : MonoBehaviour { void Start() { SerializeToFile(); } void Update() { if (Input.GetKeyDown(KeyCode.Space)) { SerializeFromFile(); } } void SerializeToFile() { MyObj obj = new MyObj(); obj.Id = 1; obj.Count = 1; obj.Name = "obj"; BinaryFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream("Myfile.bin", FileMode.Create, FileAccess.Write, FileShare.None); formatter.Serialize(stream, obj); stream.Close(); } void SerializeFromFile() { BinaryFormatter formatter = new BinaryFormatter(); Stream stream = new FileStream("Myfile.bin", FileMode.Open, FileAccess.Read, FileShare.Read); MyObj obj = (MyObj)formatter.Deserialize(stream); stream.Close(); Debug.LogError( "id:" + obj.Id+"\n"+ "count:"+obj.Count+"\n"+ "name:"+obj.Name ); } } [Serializable] public class MyObj { public int Id; public int Count; public string Name; }
- 添加Serializable属性使类可序列化
- 效率很高,能生成非常紧凑的字节流
- 反序列化时不调用构造函数
- 子类无法继承Serializable属性
-
SoapFormatter
代码类似 将BinaryFormatter改为SoapFormatter 将Myfile.bin改为Myfile.soap
- Soap文件(简单对象访问协议)是一种轻量的、简单的、基于XML的协议,主要用于WEB交互
-
XML
代码类似 将BinaryFormatter改为XmlSerializer 将Myfile.bin改为Myfile.xml
选择性序列化
NonSerialized:类可能包含不应被序列化的字段。如,某个类的一个成员变量存储着线程ID,当被反序列化时,可能线程不运行,那么这个值反序列化就没有意义
[Serializable]
public class MyObj
{
public int Id;
[NonSerialized]
public int Count;
public string Name;
}
输出Count=0
自定义序列化
有一种情况是这样:序列化好了一个文件,可是没注意文件损坏,反序列化时就会出错
ISerializable :实现此接口的对象可以自定义序列化过程,在反序列化失效时尤其有用,需要先为变量提供值以保证可以重建对象的完整状态
序列化时需要实现GetObjectData 方法,反序列化时需要用到一个特殊的构造函数
[Serializable]
public class MyObj : ISerializable
{
public int Id;
public int Count;
public string Name;
public MyObj() { }
//实现接口方法
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("a1", Id);
info.AddValue("a2", Count);
info.AddValue("a3", Name);
}
//构造函数
private MyObj(SerializationInfo info, StreamingContext context)
{
Id = info.GetInt32("a1");
Count = info.GetInt32("a2");
Name = info.GetString("a3");
}
}
其中,value键值对名称只要对应就可以
总结
- 三种方式 BinaryFormatter、SoapFormatter、XML
- 三个属性 Serializable、NonSerialized、SerializeField
- 一个接口 ISerializable
- 要小心使用序列化,因为序列化并不是运行在主线程!