一、序列化、反序列化
什么是序列化、反序列化?
- 序列化就是把数据对象转换成二进制流保存为本地文件的过程。
- 反序列化就是把储存有数据信息的二进制文件还原成数据对象的过程。
序列化的意义
- 以某种储存形式(二进制/XML,今天只讲二进制方法)使自定义对象持久化
- 方便将对象从一个地方移动到另一个地方(转移文件再反序列化读取)
- 使游戏数据不容易被直接篡改
二、XML和JSON
XML
扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进 行定义的源语言。 XML使用DTD(document type definition)文档类型定义来组织数据;格式统一,跨平台和语言,早已成为业界公认的标准。
XML是标准通用标记语言 (SGML) 的子集,非常适合 Web 传输。XML 提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。
优点:格式统一,符合标准,容易与其它系统远程交互,数据共享方便
缺点:xml文件庞大,格式复杂,占用带宽较多;服务端和客户端解析xml花费较多的时间和资源
JSON
JSON(JavaScript Object Notation)一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。可在不同平台之间进行数据交换。JSON采用兼容性很高的、完全独立于语言文本格式,同时也具备类似于C语言的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)体系的行为。这些特性使JSON成为理想的数据交换语言。
优点:数据格式比较简单,易于读写,占用带宽小,支持多种语言
缺点:可读性差
总之,XML和JSON就是数据保存的两种格式,主要用于配置文件,描述数据,存储数据,数据传输等等。
两者可以相互转换,功能类似。但是JSON比XML较好一些,但xml更通用。
XML和JSON代码对比
<team name="Dreamer">
<student>
<name>Tom</name>
<age>20</age>
<id>20111234</id>
</student>
<student>
<name>Shierly</name>
<age>19</age>
<id>20113210</id>
</student>
<student>
<name>Lili</name>
<age>21</age>
<id>20111110</id>
</student>
</team>
{
"Name" : "Dreamer",
"Number" : 3,
"Member" :
[
{
"Name" : "Tom",
"Age" : 20,
"Id" : "20111234"
},
{
"Name" : "Jack",
"Age" : 22,
"Id" : "20112312"
}
]
}
JSON的基本结构单元就是以{}包裹的一对键值对
三、在Unity中用代码编写XML
创建XML文件
public void CreateXML()
{
//xml保存的路径,注意路径。
string filepath = "E:/my.xml";
//继续判断当前路径下是否有该文件
if(!File.Exists (filepath))
{
//创建XML文档实例
XmlDocument xmlDoc = new XmlDocument();
//创建root节点,也就是最上一层节点
XmlElement root = xmlDoc.CreateElement("team");
root.SetAttribute("name", "Dreamer");
//继续创建下一层节点
XmlElement student = xmlDoc.CreateElement("student");
//继续创建下一层节点
XmlElement name = xmlDoc.CreateElement("name");
//设置节点中的数值
name.InnerText = "Tom";
XmlElement age = xmlDoc.CreateElement("age");
age.InnerText = "20";
XmlElement id = xmlDoc.CreateElement("id");
id.InnerText = "20111234";
//把节点一层一层的添加至XMLDoc中 ,请仔细看它们之间的先后顺序,这将是生成XML文件的顺序
student.AppendChild(name);
student.AppendChild(age);
student.AppendChild(id);
root.AppendChild(student);
student = xmlDoc.CreateElement("student");
name = xmlDoc.CreateElement("name");
name.InnerText = "Shierly";
age = xmlDoc.CreateElement("age");
age.InnerText = "19";
id = xmlDoc.CreateElement("id");
id.InnerText = "20113210";
student.AppendChild(name);
student.AppendChild(age);
student.AppendChild(id);
root.AppendChild(student);
student = xmlDoc.CreateElement("student");
name = xmlDoc.CreateElement("name");
name.InnerText = "Lili";
age = xmlDoc.CreateElement("age");
age.InnerText = "21";
id = xmlDoc.CreateElement("id");
id.InnerText = "20111110";
student.AppendChild(name);
student.AppendChild(age);
student.AppendChild(id);
root.AppendChild(student);
xmlDoc.AppendChild(root);
//把XML文件保存至本地
xmlDoc.Save(filepath);
}
}
其实,可以看出主要就五个操作
1.XmlElement 属性名 = xmlDoc.CreateElement("XML中的标签名"):XML中每一个标签都是 XmlElement元素,得到如下结果
<xml中的标签名></xmlz中的标签名>
// XmlElement root = xmlDoc.CreateElement("team");得到
<team></team>
2.属性名.SetAttribute("XML中的属性名", "属性名对应的属性值"):给对应的标签添加一个属性和对应的属性值
<xml中的标签名 xml中的属性名:对应的属性值>
</xmlz中的标签名>
//root.SetAtrribute("name",paoyou);得到
<team name="paoyou"></team>
3.代码中的属性名.InnerText="值":设置标签中的值
<标签名>值</标签名>
XmlElement name = xmlDoc.CreateElement("name");得到
name.InnerText = "Tom";
<name>Tom</name>
4.属性名.AppendChild(student):标签添加子标签
root.AppendChild(name);得到
<team name="paoyou">
<name>Tom</name>
</team>
更新XML文件
将第三个学生的名字修改为Jack
public void UpdateXml()
{
string filepath = "E:/my.xml";
if (File.Exists(filepath))
{
XmlDocument xmlDoc = new XmlDocument();
//根据路径将XML读取出来
xmlDoc.Load(filepath);
//得到team下的所有student节点.
XmlNodeList studentlist = xmlDoc.SelectSingleNode("team").ChildNodes;
//遍历所有子节点
foreach (XmlElement student in studentlist)
{
XmlNode name = student.SelectSingleNode("name");
if (name.InnerText.Equals("Lili"))
{
name.InnerText = "Jack";
}
}
xmlDoc.Save(filepath);
}
}
移除XML节点
public void DeleteXml()
{
string filepath = "E:/my.xml";
if (File.Exists(filepath))
{
XmlDocument xmlDoc = new XmlDocument();
//根据路径将XML读取出来
xmlDoc.Load(filepath);
XmlNode team = xmlDoc.SelectSingleNode("team");
XmlNodeList studentlist = team.ChildNodes;
foreach(XmlNode student in studentlist)
{
XmlNode name = student.SelectSingleNode("name");
if(name.InnerText.Equals("Tom"))
{
team.RemoveChild(student);
}
}
xmlDoc.Save(filepath);
}
}
xmlelement.RemoveAll()可以移除所有子节点
解析XML文件
public void LoadXml()
{
string filepath = "E:/my.xml";
if (File.Exists(filepath))
{
XmlDocument xmlDoc = new XmlDocument();
//根据路径将XML读取出来
xmlDoc.Load(filepath);
XmlElement team = (XmlElement)xmlDoc.SelectSingleNode("team");
string teamname = team.GetAttribute("name");
Console.WriteLine("这是一个名叫\"" + teamname + "\"的队伍:");
XmlNodeList studentlist = team.ChildNodes;
Console.WriteLine("一共有" + studentlist.Count + "人");
foreach (XmlNode student in studentlist)
{
XmlNode name = student.SelectSingleNode("name");
XmlNode age = student.SelectSingleNode("age");
XmlNode id = student.SelectSingleNode("id");
Console.WriteLine("姓名:" + name.InnerText + ",年龄:" + age.InnerText + ",学号:" + id.InnerText);
}
xmlDoc.Save(filepath);
}
}
四、在Unity中用代码编写JSON
生成JSON
public void CreateJson()
{
string path = "E:/json.txt";
FileInfo t = new FileInfo(path);
StreamWriter sw = t.CreateText();
StringBuilder sb = new StringBuilder();
JsonWriter writer = new JsonWriter(sb);
//相当于写下了'{'
writer.WriteObjectStart();
//相当于写下了"Name":
writer.WritePropertyName("Name");
//相当于写下了"Dreamer"
writer.Write("Dreamer");
writer.WritePropertyName("Number");
writer.Write("3");
writer.WritePropertyName("Member");
//相当于写下了'['
writer.WriteArrayStart();
writer.WriteObjectStart();
writer.WritePropertyName("Name");
writer.Write("Tom");
writer.WritePropertyName("Age");
writer.Write("20");
writer.WritePropertyName("Id");
writer.Write("20111234");
//相当于写下了'}'
writer.WriteObjectEnd();
writer.WriteObjectStart();
writer.WritePropertyName("Name");
writer.Write("Jack");
writer.WritePropertyName("Age");
writer.Write("22");
writer.WritePropertyName("Id");
writer.Write("20112312");
writer.WriteObjectEnd();
//相当于写下了']'
writer.WriteArrayEnd();
writer.WriteObjectEnd();
sw.WriteLine(sb.ToString());
sw.Close();
}
这是最原始的创建JSON文件的 方法,我们还可以直接将对象序列化
using UnityEngine;
using LitJson;
public class A
{
public string name = "yzl";
public int old = 20;
}
public class Test : MonoBehaviour
{
void Start()
{
A a = new A();
Debug.Log(JsonMapper.ToJson(a));
}
}
这样控制台输出的为{“name”:"yzl","old":20}
Json的增删改
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using LitJson;
using System.IO;
public class Test : MonoBehaviour
{
void Start()
{
StreamReader sr = File.OpenText("E:/json.txt");
string strline = sr.ReadToEnd();
JsonData jd = JsonMapper.ToObject(strline);
//修改队名
jd["Name"] = "Winer";
//添加队伍地址属性
jd["Address"] = "Sichuan";
//删除队伍人数属性
((IDictionary)jd).Remove("Number");
Debug.Log(jd.ToJson());
sr.Close();
}
}
JSON的解析查看
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using LitJson;
using System.IO;
public class Test : MonoBehaviour
{
void Start()
{
StreamReader sr = File.OpenText("E:/json.txt");
string strline = sr.ReadToEnd();
JsonData jd = JsonMapper.ToObject(strline);
Debug.Log("队伍名:" + jd["Name"]);
Debug.Log("队伍人数:" + jd["Number"]);
for (int i = 0; i < jd["Member"].Count; i++)
{
Debug.Log("姓名:" + jd["Member"][i]["Name"] + ",年龄:" + jd["Member"][i]["Age"] + ",学号:" + jd["Member"][i]["Id"]);
}
sr.Close();
}
}