数据持久化之XML
1.固定内容
<?xml version="1.0" encoding="UTF-8"?>
2.注释
<!--content-->
3.基本语法
<PlayerInfo>
<name>沈11</name>
<age>18</age>
<sex>true</sex>
<ItemList>
<Item>
<id>1</id>
<num>10</num>
</Item>
<Item>
<id>2</id>
<num>10</num>
</Item>
</ItemList>
</PlayerInfo>
4.基本规则
- 每个元素必须有关闭标签
- 元素命名规则与C#一致
- 必须有根元素
- 特殊符号需要替换
< 对应 <
> 对应 >
& 对应 &
&apos 对应 '
" 对应 "
5.属性
<itemList>
<Item id = "1" num = "10"/>
<Item id = "2" num = "20"/>
<Item id = "3" num = "30"/>
</itemList>
XML读取
C#读取XML的方法有几种
- 1.XmlDocument (把数据加载到内存中,方便读取)
- 2.XmlTextReader (以流形式加载,内存占用更少,但是是单向只读,使用不是特别方便,除非有特殊需求,否则不会使用)
- 3.Linq (以后专门讲Linq的时候讲)
1.读取XML文件
- XmlDocument xml = new XmlDocument();
- 读取文本方式1-xml.LoadXml(传入xml文本字符串)
- 读取文本方式2-xml.Load(传入路径)XmlDocument xml = new XmlDocument();
// 1.通过文本加载xml
TextAsset textAsset = Resources.Load<TextAsset>(“TestXml”);
xml.LoadXml(textAsset.text);
// 2.通过文件加载xml
xml.Load(Application.streamingAssetsPath + “/TestXml.xml”);
2.读取元素和属性
- 获取单个节点: XmlNode node = xml.SelectSingleNode(节点名)
- 获取多个节点: XmlNodeList nodeList = xml.SelectNodes(节点名)//获取xml当中的根节点
XmlNode root = xml.SelectSingleNode(“Root”);
//再通过根节点 去获取下面的子节点
XmlNode nodeName = root.SelectSingleNode(“name”);
//如果想要获取节点包裹的元素信息 直接 .InnerText
print(nodeName.InnerText);
XmlNode nodeAge = root.SelectSingleNode(“age”);
print(nodeAge.InnerText);
XmlNode nodeItem = root.SelectSingleNode(“Item”);
//第一种方式 直接 中括号获取信息
print(nodeItem.Attributes[“id”].Value);
print(nodeItem.Attributes[“num”].Value);
//第二种方式
print(nodeItem.Attributes.GetNamedItem(“id”).Value);
print(nodeItem.Attributes.GetNamedItem(“num”).Value);
//这里是获取 一个节点下的同名节点的方法
XmlNodeList friendList = root.SelectNodes(“Friend”);
存储XML
注意:存储xml文件 在Unity中一定是使用各平台都可读可写可找到的路径 1.Resources 可读 不可写 打包后找不到 × 2.Application.streamingAssetsPath 可读 PC端可写 找得到 × 3.Application.dataPath 打包后找不到 × 4.Application.persistentDataPath 可读可写找得到 √
关键类 XmlDocument 用于创建节点 存储文件 关键类 XmlDeclaration 用于添加版本信息 关键类 XmlElement 节点类
//存储有5步
//1.创建文本对象
XmlDocument xml = new XmlDocument();
//2.添加固定版本信息
//这一句代码 相当于就是创建<?xml version="1.0" encoding="UTF-8"?>这句内容
XmlDeclaration xmlDec = xml.CreateXmlDeclaration("1.0", "UTF-8", "");
//创建完成过后 要添加进入 文本对象中
xml.AppendChild(xmlDec);
//3.添加根节点
XmlElement root = xml.CreateElement("Root");
xml.AppendChild(root);
//4.为根节点添加子节点
//加了一个 name子节点
XmlElement name = xml.CreateElement("name");
name.InnerText = "唐老狮";
root.AppendChild(name);
保存Xml
Xml.Save(path);
删除节点
root.RemoveChild(node);
XmlNode和XmlElement区别
当元素没有值的时候就可以用XmlNode
需要赋值就用XmlElement(InnerText,SetAttribute / GetAttribute,TagName)
Xml序列化
string path = Application.persistentDataPath + "/Lesson1Test.xml";
using ( StreamWriter stream = new StreamWriter(path) )
{
XmlSerializer s = new XmlSerializer(typeof(Lesson1Test)); // 决定序列化翻译机器的类型
// 文件写入流,序列化对象
s.Serialize(stream, lt);
}
using的作用是代码块运行完毕后,自动调用Dispose()销毁StreamWriter
注意: 1.只能序列化公共成员public 2.不支持字典Dictionary序列化 3.可以通过特性修改节点信息 或者设置属性信息 [XmlAttribute(“Test1”)](不设置此特性默认为节点存储的Xml) 4.Stream相关要配合using使用
Xml反序列化
// 需要进行判空
if( File.Exists(path) )
{
using (StreamReader reader = new StreamReader(path))
{
XmlSerializer s = new XmlSerializer(typeof(Lesson1Test));
Lesson1Test lt = s.Deserialize(reader) as Lesson1Test;
}
}
注意:List对象 如果有默认值 反序列化时 不会清空 会往后面添加
IXmlSerializable接口(自定义序列化读写)
public class TestLesson3 : IXmlSerializable
{
public int test1 = 10;
public int test2 = 99;
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
// 三种读取方式
// 1.读属性
test1 = int.Parse(reader["Test1"]);
test2 = int.Parse(reader["Test2"]);
// 2.读节点
// 方式一
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;
}
}
}
// 3.读包裹点
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)
{
// 三种方式
// 1.写属性
writer.WriteAttributeString("Test1", test1.ToString());
writer.WriteAttributeString("Test2", test2.ToString());
// 2.写节点
writer.WriteElementString("Test1", test1.ToString());
writer.WriteElementString("Test2", test2.ToString());
// 3.写包裹节点
XmlSerializer s = new XmlSerializer(typeof(int));
writer.WriteStartElement("Test1");
s.Serialize(writer, test1);
writer.WriteEndElement();
writer.WriteStartElement("Test2");
s.Serialize(writer, test2);
writer.WriteEndElement();
}
}
自定义可Xml序列化的Dictionary示例
public class SerializeDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
reader.Read();
XmlSerializer s1 = new XmlSerializer(typeof(TKey));
XmlSerializer s2 = new XmlSerializer(typeof(TValue));
while (reader.NodeType != XmlNodeType.EndElement)
{
TKey key = (TKey)s1.Deserialize(reader);
TValue value = (TValue)s2.Deserialize(reader);
this.Add(key, value);
}
reader.Read();
}
public void WriteXml(XmlWriter writer)
{
XmlSerializer s1 = new XmlSerializer(typeof(TKey));
XmlSerializer s2 = new XmlSerializer(typeof(TValue));
foreach(KeyValuePair<TKey,TValue> pair in this)
{
s1.Serialize(writer, pair.Key);
s2.Serialize(writer, pair.Value);
}
}
}

评论(0)
暂无评论