当前位置: 首页 > news >正文

【Unity开发】数据存储——XML

一、相关介绍

1、XML介绍

XML,全称可拓展标记语言(EXtensible Markup Language),是被设计用于传输和存储数据的一种文本特殊格式。

2、优缺点

优点:格式统一,符合标准,容易与其他系统进行远程交互,数据共享比较方便。
缺点:XML文件庞大,文件格式复杂,传输占带宽;服务器端与客户端解析XML花费较多的资源和时间。

3、基本规则

①每个元素都必须有关闭标签
②元素命名规则基本遵照C#中变量名命名规则
③XML标签对大小写敏感
④XML文档必须有根元素
⑤特殊的符号应该用实体引用
在这里插入图片描述

4、XML属性

(1)属性语法

在这里插入图片描述

(2)属性和元素节点的区别(只有写法上的区别)

在这里插入图片描述

5、如何检查语法错误

①元素标签必须配对
②属性必须有引号
③注意命名
④将内容直接复制到该网站进行验证:https://www.runoob.com/xml/xml-validator.html

6、XML存放位置

①只读不写,存放在Resources或者StreamingAssets文件夹下
②动态存储,放在Application.persistentDataPath路径下

二、具体实现

1、常用功能实现

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEngine;public class LoadXml : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){#region 读取xml文件信息//方法一、读取Resources文件夹下的xml文件加载处理TextAsset textAsset = Resources.Load<TextAsset>("TestXml");print(textAsset.text);XmlDocument xml = new XmlDocument();xml.LoadXml(textAsset.text);//方法二、读取StreamingAssets文件夹下的xml文件加载处理//xml.Load(Application.streamingAssetsPath + "/Testxml.xml");#endregion#region 读取元素和属性信息//1、获取xml中的根节点XmlNode root = xml.SelectSingleNode("Root");//2、通过根节点获取下面的字节点XmlNode nodeName = root.SelectSingleNode("name");//3、获取节点包裹的元素信息print(nodeName.InnerText);//4、获取节点属性信息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);//5、获取一个节点下的同名节点的方法XmlNodeList friendList = root.SelectNodes("Friend");//遍历打印信息//方法一、使用迭代器遍历foreach (XmlNode item in friendList){print(item.SelectSingleNode("name").InnerText);print(item.SelectSingleNode("age").InnerText);}//方法二、使用for循环遍历for (int i = 0; i < friendList.Count; i++){print(friendList[i].SelectSingleNode("name").InnerText);print(friendList[i].SelectSingleNode("age").InnerText);}#endregion#region 存储xml文件信息//1、存储路径//Resources 可读 不可写 打包后找不到 x//Application.streamingAssetsPath 可读 PC端可写 找得到 x//Application.dataPath 打包后找不到 x//Application.persistentDataPath 可读可写找得到 ✔string path = Application.persistentDataPath + "/PlayerInfo2.xml";print(path);//2、存储xml文件//(1)创建文本对象XmlDocument xml1 = new XmlDocument();//(2)添加固定版本信息XmlDeclaration xmlDec = xml1.CreateXmlDeclaration("1.0", "UTF-8", "");xml1.AppendChild(xmlDec);//(3)添加根节点XmlElement root1 = xml1.CreateElement("Root");xml1.AppendChild(root1);//(4)为根节点添加子节点XmlElement name = xml1.CreateElement("name");name.InnerText = "某某某";root1.AppendChild(name);XmlElement listInt = xml1.CreateElement("int");for (int i = 0; i < 3; i++){XmlElement childNode = xml1.CreateElement("int");childNode.InnerText = i.ToString();listInt.AppendChild(childNode);}root1.AppendChild(listInt);//(5)添加属性XmlElement itemList = xml1.CreateElement("itemList");for (int i = 0; i < 3; i++){XmlElement childNode = xml1.CreateElement("Item");//添加属性childNode.SetAttribute("id", i.ToString());childNode.SetAttribute("num", (i * 10).ToString());itemList.AppendChild(childNode);}root1.AppendChild(itemList);//(6)保存xml1.Save(path);print("成功保存到文件夹:" + path);#endregion#region 修改xml文件信息//1、先判断是否存在文件if (File.Exists(path)){//2、加载后 直接添加节点 移除节点即可XmlDocument xml2 = new XmlDocument();xml2.Load(path);//移除XmlNode node = xml2.SelectSingleNode("Root").SelectSingleNode("name");node = xml2.SelectSingleNode("Root/name");print(node.InnerText);//得到自己的父节点XmlNode root2 = xml2.SelectSingleNode("Root");root2.RemoveChild(node);//添加XmlNode speed = xml2.CreateElement("moveSpeed");speed.InnerText = "20";root.AppendChild(speed);//修改后 记得保存更新xml文件xml2.Save(path);}#endregion}
}

2、字典自定义序列化与反序列化实现

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;}//自定义字典的 反序列化 规则public void ReadXml(XmlReader reader){XmlSerializer keySer = new XmlSerializer(typeof(TKey));XmlSerializer valueSer = new XmlSerializer(typeof(TValue));//要跳过根节点reader.Read();//判断 当前不是元素节点 结束 就进行 反序列化while (reader.NodeType != XmlNodeType.EndElement){//反序列化键TKey key = (TKey)keySer.Deserialize(reader);//反序列化值TValue value = (TValue)valueSer.Deserialize(reader);//存储到字典中this.Add(key, value);}reader.Read();}//自定义 字典的 序列化 规则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);}}
}

3、XML存储与读取功能封装

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;
using UnityEngine;public class XmlDataMgr
{private static XmlDataMgr instance = new XmlDataMgr();public static XmlDataMgr Instance => instance;private XmlDataMgr() { }/// <summary>/// 保存数据到xml文件中/// </summary>/// <param name="data">数据对象</param>/// <param name="fileName">文件名</param>public void SaveData(object data, string fileName){//1.得到存储路径string path = Application.persistentDataPath + "/" + fileName + ".xml";//2.存储文件using(StreamWriter writer = new StreamWriter(path)){//3.序列化XmlSerializer s = new XmlSerializer(data.GetType());s.Serialize(writer, data);}}/// <summary>/// 从xml文件中读取内容 /// </summary>/// <param name="type">对象类型</param>/// <param name="fileName">文件名</param>/// <returns></returns>public object LoadData(Type type, string fileName){//1。首先要判断文件是否存在string path = Application.persistentDataPath + "/" + fileName + ".xml";if( !File.Exists(path) ){path = Application.streamingAssetsPath + "/" + fileName + ".xml";if (!File.Exists(path)){//如果根本不存在文件 两个路径都找过了//那么直接new 一个对象 返回给外部 无非 里面都是默认值return Activator.CreateInstance(type);}}//2.存在就读取using (StreamReader reader = new StreamReader(path)){//3.反序列化 取出数据XmlSerializer s = new XmlSerializer(type);return s.Deserialize(reader);}}}
http://www.dtcms.com/a/295227.html

相关文章:

  • C++11+ 原子操作 `std::atomic`,现代并发编程的核心
  • Delegate、Action 与 Func 委托的全面解析
  • GitHub Actions打包容器,推送 AWS ECR 并使 EKS 自动拉取以完成发版部署
  • 【Java基础06】ArrayList
  • 软考 系统架构设计师系列知识点之杂项集萃(115)
  • Python 程序设计讲义(14):Python 的数据运算——数值运算
  • RabbitMQ--消息顺序性
  • Java集合去重
  • OpenMed 项目深度分析:推动医疗 NLP 领域的开源革命
  • pcie常用的查看寄存器方法
  • node.js中的path模块
  • 低速信号设计之 QSPI 篇
  • 【LeetCode数据结构】二叉树的应用(一)——单值二叉树问题、相同的树问题、对称二叉树问题、另一棵树的子树问题详解
  • Faiss中L2欧式距离与余弦相似度:究竟该如何选择?
  • Web前端入门:JavaScript 哪些地方需要 try...catch 异常捕获
  • 【图论】倍增与lca
  • Avalonia 基于MVVM的时间统计/系统时间显示 示例
  • EPSON爱普生全系列废墨垫已满清零工具分享附教程下载
  • EasyExcel 模板导出数据 + 自定义策略(合并单元格)
  • 基于深度学习的胸部 X 光图像肺炎分类系统(三)
  • Turbo Intruder 并发插件无法试用--更换新版Burpsuit解决(简单解决安装、破解问题)
  • 开源Qwen凌晨暴击闭源Claude!刷新AI编程SOTA,支持1M上下文
  • 跨境支付入门~国际支付结算(结算篇)
  • AtCoder Beginner Contest 415(ABCDE)
  • `neutron router-gateway-set` 操作失败的可能原因及解决方案
  • 深度分析Java多线程机制
  • 【智能协同云图库】智能协同云图库第六弹:空间模块开发
  • 微服务的编程测评系统6-管理员登录前端-前端路由优化
  • 【开源】WPF的数据可视化大屏解决方案——WpfMap
  • 洛谷 P11378 [GESP202412 七级] 燃烧-普及/提高-