序列化与反序列化
一、前言
游戏里,我们经常遇到这种情景:要保存一些数据为文件,方便运行时再次读取使用。这就涉及到了序列化与反序列化
二、说明
1、什么是序列化/反序列化
- 序列化:通常的来讲,就是把 对象 转成 二进制序列。可以简单的理解为把对象转成一个文件
- 反序列化:反序列化是序列化的相反操作。可以简单的理解为,是把文件转为对象的这么一个过程
2、序列化有几种方式
- 游戏中常见的序列化方法有 二进制序列化,Xml序列化, Json序列化等等。
- 接下来讲一下 二进制序列化和Xml序列化的具体操作
三、实际操作
1、准备操作
1.1、定义2个测试类
既然是需要把对象序列化为xml文件,那么为了方便测试,这里定义2个测试类
[System.Serializable]
public class Model
{
//使用[XmlAttribute]特性,生成的xml标签等于该字段名‘val1’
[XmlAttribute]
public int Val1;
//使用[XmlAttribute]特性,并指定生成的xml标签等于‘Val2-alias’,而不是默认的字段名
[XmlAttribute("Val2-alias")]
public int Val2;
//list字段 需要使用[XmlElement]特性,并起别名为ModelItem
[XmlElement("ModelItem")]
public List<ModelItem> itemList;
}
[System.Serializable]
public class ModelItem
{
[XmlAttribute]
public int id;
}
1.2、构建model测试类
接下来,我们用一个方法,来创建Model类,并为其填充一些测试数据。
/// <summary>
/// 返回一个测试model对象
/// </summary>
/// <returns></returns>
Model BuildModel()
{
Model model = new Model();
model.Val1 = 1;
model.Val2 = 2;
ModelItem modelItem1 = new ModelItem();
modelItem1.id = 123;
ModelItem modelItem2 = new ModelItem();
modelItem2.id = 456;
model.itemList = new List<ModelItem>();
model.itemList.Add(modelItem1);
model.itemList.Add(modelItem2);
return model;
}
2、Xml篇
2.1、Xml序列化
/// <summary>
/// 序列化
/// </summary>
void Test_XmlSerializ()
{
//构建model对象
Model model = BuildModel();
//执行序列化到文件的操作
FileStream fs = new FileStream(Application.dataPath+"/Resources/model.xml",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fs,Encoding.UTF8);
XmlSerializer xs = new XmlSerializer(typeof(Model));
xs.Serialize(sw,model);
//关闭文件流
sw.Close();
fs.Close();
}
- 生成的文件如下,可以看到成功的生成了文件,数据也是跟我们定义的一样
2.2、Xml反序列化
2.2.1、Xml反序列化-通过文件流
- Xml反序列化有两种方法。其一,通过文件流
/// <summary>
/// 反序列化-通过文件流
/// </summary>
void Test_XmlDeserialize_By_FileStream()
{
//传入文件路径:Application.dataPath+"/Resources/model.xml",构建文件流
FileStream fs = new FileStream(Application.dataPath+"/Resources/model.xml",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
StreamReader sr = new StreamReader(fs,Encoding.UTF8);
XmlSerializer xs = new XmlSerializer(typeof(Model));
Model model = xs.Deserialize(sr) as Model;
sr.Close();
fs.Close();
Debug.Log($"model.Val1:{model.Val1} model.Val2:{model.Val2} item1Id:{model.itemList[0].id} item2Id:{model.itemList[1].id}");
}
//打印如下
//model.Val1:1 model.Val2:2 item1Id:123 item2Id:456
2.2.1、Xml反序列化-通过字符串文本
- 通过字符串来反序列化
- 有时我们的Xml文件是放在Resources目录下的,好比上面生成的文件就在这个目录下。Resources目录下的文件在真正出包后,用纯路径是获取不到这个文件的,所以没办法用文件流来反序列化。那这种情况怎么读取呢,可以使用Resources.Load() 把字符串文本读出来,然后使用 字符串文本反序列化的方式。代码如下
/// <summary>
/// 反序列化-通过字符串文本
/// </summary>
void Test_XmlDeserialize_By_String()
{
//读取Resources/model.xml文件
TextAsset textAsset = Resources.Load<TextAsset>("model");
StringReader sr = new StringReader(textAsset.text);
XmlSerializer xs = new XmlSerializer(typeof(Model));
Model model = xs.Deserialize(sr) as Model;
Debug.Log($"model.Val1:{model.Val1} model.Val2:{model.Val2} item1Id:{model.itemList[0].id} item2Id:{model.itemList[1].id}");
}
//打印如下
//model.Val1:1 model.Val2:2 item1Id:123 item2Id:456
3、二进制篇
3.1、二进制序列化
void Test_ByteSerialize()
{
//构建model类
Model model = BuildModel();
BinaryFormatter bf = new BinaryFormatter();
FileStream fs = new FileStream(Application.dataPath+"/Resources/model.byte",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
bf.Serialize(fs,model);
fs.Close();
}
- 截图
可以看到成功的生成了model.byte文件
3.2、二进制反序列化
void Test_ByteDeserialize()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream fs = new FileStream(Application.dataPath+"/Resources/model.byte",FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
Model model = bf.Deserialize(fs) as Model;
Debug.Log($"model.Val1:{model.Val1} model.Val2:{model.Val2} item1Id:{model.itemList[0].id} item2Id:{model.itemList[1].id}");
}
//打印如下
//model.Val1:1 model.Val2:2 item1Id:123 item2Id:456