一.XML基础语法

  1.XML结构:XML是一种树结构的文本

  2.XML注释:格式:<!--在其中书写注释-->,在注释中可以单行注释也可以多行注释

  3.固定内容:<?xml version="1.0" encoding="UTF-8"?>版本和编码信息

  4.基本语法:<root>...</root>,一个节点的内容使用尖括号包裹节点名称开始,尖括号包裹斜杠和节点名称结束,子节点的内容被包裹在这两个尖括号中间。通过在最下层的子节点的首尾尖括号之间包裹数据的形式保存数据。这种节点的树形结构和对象这种引用类型中包含值类型(没有子节点)和其他引用类型(有子节点)的形式是一致的。

  5.属性:和元素节点只是写法上的区别,相当于简化的节点写法

    1)<Father name="爸爸" age="52">...</Father>

    2)<Father name="爸爸" age="52"/>

二.Unity中XML的存放位置

  1.Resources 只读文件,打包后找不到

  2.Application.streamingAssetsPath 可读,PC端可写,能找到

  3.Application.dataPath 打包后找不到

  4.Application.persistentDataPath 可读可写能找到

三.Unity中读取xml文件信息

  1.常见的读取方式

    1)XmlDocument:把数据加载到内存中,方便读取

    2)XmlTextReader:以流形式加载数据,内存占用更少,但是单向只读

    3)Linq

  2.使用XmlDocument读取和存储信息的一些方法

    1)LoadXml成员方法:将字符串加载到xml中

    2)Load成员方法:将路径对应的xml文件的内容加载到xml中

    3)SelectSingleNode成员方法:得到单个节点,存储为XmlNode对象,XmlNode中同样有这个成员方法得到节点的单个子节点

    4)节点对象.Attributes[属性名].Value得到属性值,或者节点对象.Attributes.GetNamedItem(属性名).Value可以达到同样的效果

    5)SelectNodes成员方法:得到节点下的所有同名节点,存储为XmlNodeList对象

    6)CreateXmlDeclaration成员方法:创建固定版本和编码信息

    7)AppendChild:把节点对象添加到xml中

    8)CreateElement:创建节点

    9)InnerText属性:节点中存储的信息

    10)SetAttribute成员方法:添加属性

    11)Save成员方法:保存

  3.使用XmlDocument读取和存储信息的一些重要类

    1)XmlNode:读取出的单个节点信息类

    2)XmlNodeList:读取出的多个同名节点信息类存储到一个list中

    3)XmlElement:存储时的单个节点信息类

    4)XmlDeclaration:存储时创建出的xml文件固定版本和编码等信息类

四.xml序列化和通用保存加载类

  1.xml序列化

    1)序列化:把对象转化为可传输的字节序列过程称为序列化

       反序列化:将字节序列还原为对象的过程称为反序列化

    2)using关键字:using关键字的格式和if类似,都是在后面跟上一个小括号和一个大括号。using关键字后面的小括号中的内容一般是声明一个对象,这个对象需要是继承IDispose接口的对象,在大括号中的代码块调用完毕后,系统会自动调用小括号中对象的Dispose方法将对象释放。一般用于内存占用较大或者读写时操作。

    3)序列化类XmlSerializer和输出流StreamWriter:序列化类的对象相当于一个翻译机器,负责将对象进行序列化翻译,而输出流的对象相当于传送带,负责传输序列化前后的信息。因此,new一个XmlSerializer类对象时需要指定类型(翻译的类的类型),而new一个StreamWriter类对象时需要指定文件地址(传动带的终点),“输入”或者“输出”相当于是说的传送方向(传送带是单向的);使用Serialize方法进行序列化翻译时需要指定流对象(传送带)和要序列化的对象。

    4)示例:

     TestClass test = new TestClass();
string path = Application.persistentDataPath + "/TestClass.xml"; //尝试创建一个文件流,需要指定文件地址,会自动打开文件(如果有文件直接打开,如果没有文件自动新建一个文件再打开)
//using括号中声明的对象会在大括号中语句块结束后自动释放
//using在语句块结束后自动调用对象的Dispose方法(继承IDispose接口),让对象自行销毁
//一般在内存占用较大或者有读写操作时使用
using(StreamWriter stream = new StreamWriter(path))
{
//序列化对象相当于翻译机器,将对象翻译为序列化文件,需要指定机器能翻译的对象的类型;流相当于传送带,负责运输翻译的对象和结果
//创建序列化对象,需要指定这个序列化对象的类型
XmlSerializer xs = new XmlSerializer(typeof(TestClass));
//调用序列化对象的Serialize方法将对象test通过stream流序列化
xs.Serialize(stream,test);
}

    进行序列化的代码。

public class TestClass
{
public int testPublic = 1;
private int testPrivate = 2;
protected int testProtected = 3;
internal int testInternal = 4; public string testStrPublic = "12";
public int testPro { get; set; } public TestClass2 testClass = new TestClass2(); } public class TestClass2
{
public int test1 = 1;
public float test2 = 2.2f;
public bool test3 = false;
}

    被序列化的对象的模板类。

<?xml version="1.0" encoding="utf-8"?>
<TestClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<testPublic>1</testPublic>
<testStrPublic>12</testStrPublic>
<testClass>
<test1>1</test1>
<test2>2.2</test2>
<test3>false</test3>
</testClass>
<testPro>0</testPro>
</TestClass>

    序列化出来的xml文件内容,可以看到只有public的属性和变量被存储下来了。

  注意:这种序列化方式支持数组、list等,但是不支持dictionary。

    5)使用特性为序列化进行自定义

      [XmlAttribute()]:在类中的属性或变量上加上这个特性,这个属性或变量在序列化时会存储为属性,可以在括号中指定自定义属性名称

      [XmlElement()]:在类中的属性或变量上加上这个特性,这个属性或变量在序列化时存储为节点(默认也是存储为节点),可以在括号中指定自定义节点名称

      [XmlArrayItem()]:在类中的数组属性(变量)前加上这个特性,在括号内传入自定义数组的元素存储为的节点名称

      [XmlArray()]:在类中的list属性(变量)前加上这个特性,在括号内传入自定义的list的元素存储为的节点名称

  2.xml反序列化

    序列化和反序列化的方法是一一对应的,把序列化过程反过来就可以,示例:

        string path = Application.persistentDataPath + "/TestClass.xml";
TestClass test1 = null;
using (StreamReader stream = new StreamReader(path))
{
XmlSerializer xs = new XmlSerializer(typeof(TestClass));
test1 = (TestClass)xs.Deserialize(stream);
}

    注意:在反序列化时,如果类中声明变量时list类型的变量有默认值,会调用add方法往list中添加值,也就是说反序列化后默认值和反序列化的值都会存储在list变量中,因此尽量不要在创建对象时为list赋初值。

  3.IXmlSerializable接口

    继承IXmlSerializable接口能够自定义类的序列化和反序列化。继承后需要重写方法:

    /// <summary>
/// 返回结构
/// </summary>
/// <returns></returns>
public XmlSchema GetSchema()
{
return null;
} /// <summary>
/// 反序列化时自动调用的方法
/// </summary>
/// <param name="reader"></param>
public void ReadXml(XmlReader reader)
{
//读属性
this.testStrPublic = reader["testStrPublic"]; //读节点
//方式一:
//每次reader读取一块内容(一个尖括号的内容或者尖括号包裹的信息),先读取节点开始的尖括号,再读取节点中的内容,再read就继续读取节点结束的尖括号
reader.Read();
reader.Read();
this.testPublic = int.Parse(reader.Value);
//方式二:
//循环读取
while (reader.Read())
{
//判断读取出的类型,是节点开始标签(XmlNodeType.Element)、节点中包裹的内容(XmlNodeType.Text)还是节点结束标签(XmlNodeType.EndElement),根据读取出的类型作处理
if (reader.NodeType == XmlNodeType.Text)
{
//Name属性是节点的名称,根据节点名称作响应的处理
switch (reader.Name)
{
case "testPublic":
break;
}
}
} //读包裹节点
XmlSerializer xs = new XmlSerializer(this.testStrPublic.GetType());
//跳过根节点
reader.Read();
reader.ReadStartElement("testStrPublic");
this.testStrPublic = (string)xs.Deserialize(reader);
reader.ReadEndElement();
} /// <summary>
/// 序列化时自动调用的方法
/// </summary>
/// <param name="writer"></param>
public void WriteXml(XmlWriter writer)
{
//写属性
writer.WriteAttributeString("testStrPublic", this.testStrPublic); //写节点
writer.WriteElementString("testStrPublic", this.testStrPublic); //写包裹节点
writer.WriteStartElement("testStrPublic");
XmlSerializer xs = new XmlSerializer(this.testStrPublic.GetType());
xs.Serialize(writer,this.testStrPublic);
writer.WriteEndElement();
}

  4.让Dictionary支持xml序列化和反序列化

    只需要重写一个继承Dictionary的类,这个类再实现IXmlSerializable接口,重写方法即可。

public class SerializerDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
public XmlSchema GetSchema()
{
return null;
} public void ReadXml(XmlReader reader)
{
XmlSerializer keyXS = new XmlSerializer(typeof(TKey));
XmlSerializer valueXS = new XmlSerializer(typeof(TValue));
//跳过根节点
reader.Read();
//没有到根节点的结束尖括号,就可以一直读取
while(reader.NodeType != XmlNodeType.EndElement)
{
TKey key = (TKey)keyXS.Deserialize(reader);
TValue value = (TValue)valueXS.Deserialize(reader);
this.Add(key, value);
}
} public void WriteXml(XmlWriter writer)
{
XmlSerializer keyXS = new XmlSerializer(typeof(TKey));
XmlSerializer valueXS = new XmlSerializer(typeof(TValue));
foreach(KeyValuePair<TKey,TValue> pair in this)
{
keyXS.Serialize(writer, pair.Key);
valueXS.Serialize(writer, pair.Value);
}
}
}

  5.xml管理类

public class XmlDataManager
{
//单例模式模块
private static XmlDataManager instance;
public static XmlDataManager Instance
{
get
{
if (instance == null)
instance = new XmlDataManager();
return instance;
}
}
private XmlDataManager() { } /// <summary>
/// 数据存储类
/// </summary>
/// <param name="data">存储的数据对象</param>
/// <param name="fileName">文件名</param>
public void SaveData(object data,string fileName)
{
string path = Application.persistentDataPath + "/" + fileName + ".xml";
using(StreamWriter writer = new StreamWriter(path))
{
XmlSerializer xs = new XmlSerializer(data.GetType());
xs.Serialize(writer, data);
}
} /// <summary>
/// 加载对象
/// </summary>
/// <param name="type">对象类型</param>
/// <param name="fileName">文件名称</param>
/// <returns></returns>
public object LoadData(Type type,string fileName)
{
string path = Application.persistentDataPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
path = Application.persistentDataPath + "/" + fileName + ".xml";
if (!File.Exists(path))
{
return Activator.CreateInstance(type);
}
}
object result = null;
using(StreamReader reader = new StreamReader(path))
{
XmlSerializer xs = new XmlSerializer(type);
result = xs.Deserialize(reader);
}
return result;
}
}

XML数据持久化学习笔记的更多相关文章

  1. Java EE数据持久化框架笔记 • 【目录】

    章节 内容 实践练习 Java EE数据持久化框架作业目录(作业笔记) 第1章 Java EE数据持久化框架笔记 • [第1章 MyBatis入门] 第2章 Java EE数据持久化框架笔记 • [第 ...

  2. 大数据 -- kafka学习笔记:知识点整理(部分转载)

    一 为什么需要消息系统 1.解耦 允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束. 2.冗余 消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险.许多 ...

  3. tensorflow拟合随机生成的三维数据【学习笔记】

    平台信息:PC:ubuntu18.04.i5.anaconda2.cuda9.0.cudnn7.0.5.tensorflow1.10.GTX1060 作者:庄泽彬(欢迎转载,请注明作者) 说明:感谢t ...

  4. XSD(XML Schema Definition)学习笔记

    今天学习了XSD相关的知识,为了以后查找的方便,写一些笔记. 一.什么是XSD? 1.XSD全称:XML Schema Definition.XML Schema 的作用是定义 XML 文档的合法构建 ...

  5. Web客户端数据存储学习笔记——Cookie

    今天对登录访问的安全以及web客户端存储做了一些大致的学习,决定在这方面加深理解,记录在博客里.第一个接触到的是Cookie... WHAT? WHY? HOW? 在学习cookie的使用时发现其名称 ...

  6. EF code First数据迁移学习笔记(转)

    转自:http://www.cnblogs.com/icyJ/p/migration.html 准备工作 1.新建一个控制台项目, 在"程序包管理控制台"执行 Install-pa ...

  7. 通过程序校验xml文档学习笔记

    校验xml文档,可以通过程序来校验,利用一段js代码即可. 各行代码的含义已经写出,运行这个html文件,检验如下xml代码: 结果如下: 如果xml文档出现错误: 结果如下: 其中,obj.asyn ...

  8. SuperMap 9D 实时数据服务学习笔记

    SuperMap 在9月份发布了结合大数据技术的9D新产品,今天就和大家介绍下iServer9D中的实时数据服务. 1.技术框架 结合Spark的streaming流处理框架,将各种数据进行批量处理. ...

  9. EF code First数据迁移学习笔记

    准备工作 1.新建一个控制台项目, 在"程序包管理控制台"执行 Install-package EntityFramework  //安装EF环境 2.在项目下新建类(Paper) ...

随机推荐

  1. You Don't Know Chrome Features

    You Don't Know Chrome Features URL auto convert to QR Code click the tab URL address click QRCode ic ...

  2. taro swiper & scroll tabs

    taro swiper & scroll tabs https://taro-docs.jd.com/taro/docs/components/viewContainer/swiper.htm ...

  3. NGK Global技术开源,开启跨链全生态

    消息显示,新兴公链项目NGK Global已经完成了自己的开源计划,基于自己创新性的跨链通讯交互方案,开源后的NGK Global将面向全生态节点,提供高效.自由.无边界的公链生态系统. 目前,大家对 ...

  4. 《Effective Java》总结

    导语 <Effective Java>是和<Thinking in java>齐名的java进阶书籍.作者参与了JDK标准库的编写工作,对于此书的学习,让我收获很多.好记性不如 ...

  5. 缓存cache和缓冲区buffer

    一.cache 1.cache的定义.从宏观上讲,缓存是处理速度不匹配的问题.可以是静态缓存(内存缓存.磁盘缓存).动态缓存(前端的缓存)和数据库缓存.另一个角度,从CPU来看,可以是寄存器和内存之间 ...

  6. springcloud alibaba-nacos配置中心

    nacos除了充当注册中心外,还能作为配置中心,下面进行演示. 1. 创建 模块,用于读取 nacos配置中心的统一配置 2. 添加依赖 <dependencies> <!-- na ...

  7. PID算法验证

    算法: struct PID { float kp; float kpnfac; float ki; float kinfac; float kd; }; float gCurPPM = 1300; ...

  8. 写了一个vue+antdv的后台管理模板

    1,项目简介 写在前面===>这是一个vue+antdv的后台管理模板 项目地址: https://github.com/BaiFangZi/vue-antd-manage 1.1,概述 ​ 最 ...

  9. KDE 桌面不显示背景和状态栏

    在arch的一次更新后,kde的桌面背景,插件,状态栏变成了一片黑,如下图所示. 解决办法:删除/home/stone/.config/plasma-org.kde.plasma.desktop-ap ...

  10. HDOJ-2181(深搜记录路径)

    哈密顿绕行世界问题 HDOJ-2181 1.本题是典型的搜索记录路径的问题 2.主要使用的方法是dfs深搜,在输入的时候对vector进行排序,这样才能按照字典序输出. 3.为了记录路径,我使用的是两 ...