1.序列化
定义: 把对象转化为可传输的字节序列过程称为序列化。
xml序列化
public class Lesson1Test
{
[XmlElement("testPublic123123")]
public int testPublic;
private int testPrivate;
protected int testProtected;
internal int testInternal;
public string testPUblicStr;
public int testPro { get; set; }
public Lesson1Test2 testClass = new Lesson1Test2();
public int[] arrayInt;
[XmlArray("IntList")]
[XmlArrayItem("Int32")]
public List<int> listInt;
public List<Lesson1Test2> listItem;
//不支持字典
//public Dictionary<int, string> testDic = new Dictionary<int, string>() { { 1, "123" } };
}
//1.第一步准备一个数据结构类
Lesson1Test lt = new Lesson1Test();
//2.进行序列化
// 关键知识点
// XmlSerializer 用于序列化对象为xml的关键类
// StreamWriter 用于存储文件
// using 用于方便流对象释放和销毁
//第一步:确定存储路径
string path = Application.persistentDataPath + "/Lesson1Test.xml";
print(Application.persistentDataPath);
//第二步:结合 using知识点 和 StreamWriter这个流对象 来写入文件
// 括号内的代码:写入一个文件流 如果有该文件 直接打开并修改 如果没有该文件 直接新建一个文件
// using 的新用法 括号当中包裹的声明的对象 会在 大括号语句块结束后 自动释放掉
// 当语句块结束 会自动帮助我们调用 对象的 Dispose这个方法 让其进行销毁
// using一般都是配合 内存占用比较大 或者 有读写操作时 进行使用的
using ( StreamWriter stream = new StreamWriter(path) )
{
//第三步:进行xml文件序列化
XmlSerializer s = new XmlSerializer(typeof(Lesson1Test));
//这句代码的含义 就是通过序列化对象 对我们类对象进行翻译 将其翻译成我们的xml文件 写入到对应的文件中
//第一个参数 : 文件流对象
//第二个参数: 想要备翻译 的对象
//注意 :翻译机器的类型 一定要和传入的对象是一致的 不然会报错
s.Serialize(stream, lt);
}
//补充一些特性可以修改节点名和设置属性信息
[XmlElement("testPublic123123")]
[XmlArray("IntList")]
[XmlArrayItem("Int32")]
[XmlAttribute("Test1")]
2.反序列化
定义:把字节序列还原为对象的过程称为反序列化。
using System.IO;
//判断文件是否存在需要IO头文件
string path = Application.persistentDataPath + "/Lesson1Test.xml";
if( File.Exists(path) )
// 1.using 和 StreamReader
// 2.XmlSerializer 的 Deserialize反序列化方法
//读取文件
using (StreamReader reader = new StreamReader(path))
{
//产生了一个 序列化反序列化的翻译机器
XmlSerializer s = new XmlSerializer(typeof(Lesson1Test));
Lesson1Test lt = s.Deserialize(reader) as Lesson1Test;
}
//注意:List对象 如果有默认值 反序列化时 不会清空 会往后面添加
3.IXmlSerializable接口
定义:C# 的XmlSerializer 提供了可拓展内容,可以让一些不能被序列化和反序列化的特殊类能被处理,让特殊类继承 IXmlSerializable 接口实现其中的方法即可
提供一个继承了该接口的类
public class TestLesson3 : IXmlSerializable
{
public int test1 = 10;
public int test2 = 99;
//默认写return null即可;
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
//读属性
//test1 = int.Parse(reader["Test1"]);
//test2 = int.Parse(reader["Test2"]);
//读节点
//方式一
//reader.Read();//这时读到的是节点
//reader.Read();//这时读到的才是值
//test1 = int.Parse(reader.Value);//得到值内容
//reader.Read();//得到节点尾部配对
//reader.Read();//读到节点开头
//reader.Read();//读到值
//test2 = int.Parse(reader.Value);//获取值内容
//方式二
//while (reader.Read())
//{
// if(reader.NodeType == XmlNodeType.Element)
// {
// switch (reader.Name)
// {
// case "Test1":
// reader.Read();
// test1 = int.Parse(reader.Value) ;
// break;
// case "Test2":
// reader.Read();
// test2 = int.Parse(reader.Value);
// break;
// }
// }
//}
//读包裹点
XmlSerializer s = new XmlSerializer(typeof(int));
//过根节点
reader.Read();
reader.ReadStartElement("Test1");
test1 = (int)s.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement("Test2");
test1 = (int)s.Deserialize(reader);
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
//写属性
//writer.WriteAttributeString("Test1", test1.ToString());
//writer.WriteAttributeString("Test2", test2.ToString());
//写节点
//writer.WriteElementString("Test1", test1.ToString());
//writer.WriteElementString("Test2", test2.ToString());
//写包裹节点
XmlSerializer s = new XmlSerializer(typeof(int));
writer.WriteStartElement("Test1");
s.Serialize(writer, test1);
writer.WriteEndElement();
writer.WriteStartElement("Test2");
s.Serialize(writer, test2);
writer.WriteEndElement();
}
}
对上面这个类 进行 序列化与反序列化
TestLesson3 t = new TestLesson3();
using (StreamWriter writer = new StreamWriter(Application.persistentDataPath + "/test.xml"))
{
XmlSerializer s = new XmlSerializer(typeof(TestLesson3));
s.Serialize(writer, t);
}
using(StreamReader reader = new StreamReader(Application.persistentDataPath + "/test.xml"))
{
XmlSerializer s = new XmlSerializer(typeof(TestLesson3));
t = s.Deserialize(reader) as TestLesson3;
}
4.让IXmlSerializer接口支持Dictionnary数据结构
自己写一个SerizlizerDictionnary
using System.Collections;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using UnityEngine;
public class SerizlizerDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public XmlSchema GetSchema()
{
return null;
}
/// <summary>
/// 自定义字典的序列化规则
/// </summary>
/// <param name="writer"></param>
public void WriteXml(XmlWriter writer)
{
//声明键和值的“翻译器”
XmlSerializer keySer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSer = new XmlSerializer(typeof(TValue));
//遍历自己的键和值
foreach (KeyValuePair<TKey, TValue> kv in this)
{
//对键值对序列化
keySer.Serialize(writer, kv.Key);
valueSer.Serialize(writer, kv.Value);
}
}
/// <summary>
/// 自定义字典的反序列化规则
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
//声明键和值的“翻译器”
XmlSerializer keySer = new XmlSerializer(typeof(TKey));
XmlSerializer valueSer = new XmlSerializer(typeof(TValue));
//跳过根节点
reader.Read();
//只要没读到End节点 就一直读
while (reader.NodeType != XmlNodeType.EndElement)
{
//解析键
TKey key = (TKey)keySer.Deserialize(reader);
//解析值
TValue value = (TValue)valueSer.Deserialize(reader);
//把读到的值加进去
this.Add(key, value);
}
//把End节点读了,避免影响之后的数据读取
reader.Read();
}
}
使用SerizlizerDictionary<int, string> dic
public class TestLesson4
{
public int test1;
public SerizlizerDictionary<int, string> dic;
}
public class Lesson4 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
TestLesson4 tl4 = new TestLesson4();
tl4.dic = new SerizlizerDictionary<int, string>();
tl4.dic.Add(1, "123");
tl4.dic.Add(3, "321");
string path = Application.persistentDataPath + "/TestLesson4.xml";
using (StreamWriter writer = new StreamWriter(path))
{
XmlSerializer s = new XmlSerializer(typeof(TestLesson4));
s.Serialize(writer,tl4);
}
}
}