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

unity进阶学习笔记:json和xml

1早期的数据格式

在早期程序开发中一个简单且常用的数据格式为CSV。该格式单纯依靠逗号来分割数据。目前windows的office依然支持CSV解析,我们可以试着新建一个txt文件,在里面加入逗号分隔的信息:

a, 1, 15, 30, true

将txt文件后缀改为csv,可以看到系统自动生成了一个excel表格,由空格分隔的每一项都成了表格的一个单元。但显然这种方法可读性很差,因此对于存储大量数据不常用

2 json

json是一种“数组+对象” 的数据存储方式,其中[ ]内为数组,{ }内为对象,例如

{"Persons":[{"name":"a","age":18},{"name":"b","age":17}]
}

unity自带json数据创建和解析的功能JsonUtility。

示例:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;[Serializable]
public class Person {public string name;public int age;
}[Serializable]
public class Persons {public Person[] persons;
}public class JsonUtilityTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){Person person = new Person();person.name = "a";person.age = 18;Person person2 = new Person();person2.name = "b";person2.age = 17;Persons persons = new Persons();persons.persons = new Person[] {person, person2};string jsonStr = JsonUtility.ToJson(persons);Debug.Log(jsonStr);Persons ps = JsonUtility.FromJson<Persons>(jsonStr);foreach (Person p in ps.persons) {Debug.Log(p.name);}}}

1

using System;

要使用JsonUtility工具,要先在文件中引入System

2

[Serializable]
public class Person {public string name;public int age;
}[Serializable]
public class Persons {public Person[] persons;
}

这里我们创建两个类Person和Persons用于示例。在类前面的标记[Serializable]代表可序列化,只有带有该标记的类才能转化为json格式

3

string jsonStr = JsonUtility.ToJson(persons);

在我们创建并赋值Persons对象后,使用JsonUtility.ToJson()方法即可将对象自动转化为json文件,其内容如下:
{“persons”:[{“name”:“a”,“age”:18},{“name”:“b”,“age”:17}]}

Persons ps = JsonUtility.FromJson<Persons>(jsonStr);

要解析json文件,我们使用方法JsonUtility.FromJson<类型>()得到json文件最外层的数据类型,然后即可对该数据进行层层拆包得到里面的数据

除了系统自带的JsonUtility方法,还有很多常用的第三方json数据处理方法,如LitJson

下载LitJson的dll文件后,在unity Assets文件夹下面创建Plugins文件夹,并把LitJson.dll放入该文件夹。在C#脚本中引入LitJson即可使用LitJson文件

LitJson使用示例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;public class Heros {public Hero[] heros;
}public class Hero {public string name;public int age;
}public class TestLitJson : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){fun3();}void fun1() {Hero hero1 = new Hero();hero1.name = "Superman";hero1.age = 35;Hero hero2 = new Hero();hero2.name = "Batman";hero2.age = 38;Heros heros = new Heros();heros.heros = new Hero[] {hero1, hero2};string jsonStr = JsonMapper.ToJson(heros);Debug.Log(jsonStr);Heros hs = JsonMapper.ToObject<Heros>(jsonStr);Debug.Log(hs.heros[1].name);}// using JsonData typevoid fun2() {JsonData jd1 = new JsonData();jd1.SetJsonType(JsonType.Object);jd1["name"] = "Superman";jd1["age"] = 35;JsonData jd2 = new JsonData();jd2.SetJsonType(JsonType.Object);jd2["name"] = "Batman";jd2["age"] = 38;JsonData jds = new JsonData();jds.SetJsonType(JsonType.Array);jds.Add(jd1);jds.Add(jd2);JsonData heroJd = new JsonData();heroJd.SetJsonType(JsonType.Object);heroJd["heros"] = jds;Debug.Log(heroJd.ToJson());}void fun3() {string jsonStr = "{'heros':[{'name':'Superman','age':35},{'name':'Batman','age':38}]}";JsonData herosJd = JsonMapper.ToObject(jsonStr);JsonData heros = herosJd["heros"];foreach (JsonData heroJd in heros) {Debug.Log(heroJd["name"].ToString() + " " + (int)heroJd["age"]);}}
}

1

    void fun1() {Hero hero1 = new Hero();hero1.name = "Superman";hero1.age = 35;Hero hero2 = new Hero();hero2.name = "Batman";hero2.age = 38;Heros heros = new Heros();heros.heros = new Hero[] {hero1, hero2};string jsonStr = JsonMapper.ToJson(heros);Debug.Log(jsonStr);Heros hs = JsonMapper.ToObject<Heros>(jsonStr);Debug.Log(hs.heros[1].name);}

和JsonUtility类似,LitJson可以根据一个类创建json文件,使用JsonMapper.ToJson文件

要解析Json文件,使用JsonMapper.ToObject方法,可得到Json文件解析后的对象

2

    // using JsonData typevoid fun2() {JsonData jd1 = new JsonData();jd1.SetJsonType(JsonType.Object);jd1["name"] = "Superman";jd1["age"] = 35;JsonData jd2 = new JsonData();jd2.SetJsonType(JsonType.Object);jd2["name"] = "Batman";jd2["age"] = 38;JsonData jds = new JsonData();jds.SetJsonType(JsonType.Array);jds.Add(jd1);jds.Add(jd2);JsonData heroJd = new JsonData();heroJd.SetJsonType(JsonType.Object);heroJd["heros"] = jds;Debug.Log(heroJd.ToJson());}

除了利用对象创建Json文件,LitJson还支持不创建对象,直接使用JsonData创建Json文件。JsonData类型包括了Int Double Boolean Array Object等常用类型。

在上面代码中,我们创建JsonData类jd1,之后使用SetJsonType将其类型设为Object(这一句可以省略,LitJson会自动判断数据类型)。

对于Object类,使用键值对来添加值,对于数组,使用Add方法添加元素

void fun3() {string jsonStr = "{'heros':[{'name':'Superman','age':35},{'name':'Batman','age':38}]}";JsonData herosJd = JsonMapper.ToObject(jsonStr);JsonData heros = herosJd["heros"];foreach (JsonData heroJd in heros) {Debug.Log(heroJd["name"].ToString() + " " + (int)heroJd["age"]);}}

JsonMapper.ToObject方法除了支持使用泛型将Json数据解析成特定类型,还可以不使用泛型,解析完的数据默认类型全部为JsonData类型,包括内部的所有类的数据。因此在Debug.Log中我们要先将name和age分别转换为String和int类型

2 xml

xml是一种常用的标记语言,语法和html很类似,都由节点组成。我们以下面例子来讲解

<?xml version="1.0" encoding="utf-8"?>
<root><heros><hero id="1"><name>Superman</name><age>35</age></hero><hero id="2"><name>Batman</name><age>37</age></hero><hero id="3"><name>Spiderman</name><age>30</age></hero></heros>
</root>

1

<?xml version="1.0" encoding="utf-8"?>

这一句用于声明xml格式,标明版本和使用编码

2

 <root></root>

为根节点,根节点只能有一个。其他所有节点在根节点内部。

3 <hero id="1"> <name>Superman</name> <age>35</age> </hero>

对于一个节点,里面要么保存字符串值,要么保存一个子节点(不可同时保存)。节点尖括号内部可以添加属性(即为节点变量),属性值必须包括在""里面

解析xml文件(方法1)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml;public class XMLTest : MonoBehaviour
{// Start is called before the first frame updatevoid Start(){parseXml();}void parseXml() {// xml文档类XmlDocument doc = new XmlDocument();doc.Load(Application.dataPath + "/XML/testXml.xml");// rootXmlElement rootEle = doc.LastChild as XmlElement;   // herosXmlElement herosEle = rootEle.FirstChild as XmlElement;// heorforeach(XmlElement heroEle in herosEle.ChildNodes) {string id = heroEle.GetAttribute("id");string name = heroEle.ChildNodes[0].InnerText;string age = heroEle.ChildNodes[1].InnerText;Debug.Log(id + name + age);}}
}

在文件开头要引入System.Xml以使用xml工具

xml文件类型称为XmlDocument。我们先创建新的XmlDocument对象并导入刚才创建的xml文件

LastChild FirstChild方法用于获取节点的第一个和最后一个元素。ChildNodes数组保存节点里面所有元素。获取到的元素类型XmlNode,该类型为XmlElement的子类,因此获取到XmlElement需要进行类型转换

GetAttribute方法用于获取节点内的属性。要得到节点内保存的值使用方法InnerText

解析xml文件(方法2)

    void parseXml2() {XmlDocument doc = new XmlDocument();doc.Load(Application.dataPath + "/XML/testXml.xml");XmlNodeList list = doc.SelectNodes("/root/heros/hero/name");foreach (XmlElement element in list) {Debug.Log(element.InnerText);}}

除了常规从根目录进行解析,我们可以实现XPath直接通过文件路径访问到特定的节点。在上面例子中,SelectNodes()根据给出的XPath路径找到所有符合该路径的节点,得到结果Superman,Batman,Spiderman

XPath路径还有几种特殊写法
1 相对路径

XmlNodeList list = doc.SelectNodes(“//name”);

//代表使用相对路径。此时我们会查找到所有名为name的节点。不过直接使用相对路径查找要遍历所有节点,效率较低

2 访问第几个节点

XmlNodeList list = doc.SelectNodes(“//heros/hero[last()-1]/name”)

在节点后面[ ]中可以输入要访问第几个节点,注意第一个节点编号为1不是0.last()为最后一个节点的编号

3 访问前几个节点

XmlNodeList list = doc.SelectNodes(“//heros/hero[position()< 3]/name”);

在[ ]中position()可以用于访问前几个节点,上面的position()< 3代表访问1,2节点

4 根据节点属性值访问节点

XmlNodeList list = doc.SelectNodes(“//heros/hero[@id=2]/name”);

在[ ]中@id=2代表访问所有有id属性的节点中,id值为2的节点。如果直接为@id代表访问所有有id属性的节点

构建XML文件

    void createXml() {XmlDocument doc = new XmlDocument();XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", "");doc.AppendChild(dec);XmlElement rootEle = doc.CreateElement("root");doc.AppendChild(rootEle);XmlElement herosEle = doc.CreateElement("heros");rootEle.AppendChild(herosEle);string[] names = new string[] {"Superman", "Batman", "Spiderman"};string[] ages = new string[] {"35", "37", "20"};for (int i = 0; i < 3; i++) {XmlElement heroEle = doc.CreateElement("hero");herosEle.AppendChild(heroEle);XmlElement nameEle = doc.CreateElement("name");nameEle.InnerText = names[i];heroEle.AppendChild(nameEle);XmlElement ageEle = doc.CreateElement("age");ageEle.InnerText = ages[i];heroEle.AppendChild(ageEle);XmlAttribute id = doc.CreateAttribute("id");id.Value = i + "";heroEle.Attributes.Append(id);}doc.Save(Application.dataPath + "/XML/test2.xml");}

1

XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", "");

这一句用于创建XML声明,也就是XML文件开头的<?xml version="1.0" encoding="utf-8"?>

2

XmlElement rootEle = doc.CreateElement("root");
doc.AppendChild(rootEle);

创建根节点名称root,并在文件根目录添加改节点。后面添加节点的语句写法相同

3

XmlElement nameEle = doc.CreateElement("name");
nameEle.InnerText = names[i];
heroEle.AppendChild(nameEle);

对有内容的节点,使用InnerText来填充内容,再把该节点加入到其父节点。

4

XmlAttribute id = doc.CreateAttribute("id");
id.Value = i + "";
heroEle.Attributes.Append(id);

要为一个节点添加属性,首先创建XmlAttribute对象,再把该对象加入节点的Attribute中,方法和添加子节点类似

5

doc.Save(Application.dataPath + "/XML/test2.xml");

保存XML文件到指定路径

相关文章:

unity进阶学习笔记:json和xml

1早期的数据格式 在早期程序开发中一个简单且常用的数据格式为CSV。该格式单纯依靠逗号来分割数据。目前windows的office依然支持CSV解析&#xff0c;我们可以试着新建一个txt文件&#xff0c;在里面加入逗号分隔的信息&#xff1a; a, 1, 15, 30, true 将txt文件后缀改为csv&…...

数据结构之初识树与堆

前言&#xff1a;前面学习了顺序表&#xff0c;队列&#xff0c;栈&#xff0c;链表&#xff0c;我们知道他们都是一种线性表&#xff0c;是一种线性结构&#xff0c;而除此之外&#xff0c;仍有许多我们还没认识的结构&#xff0c;比如树形结构&#xff0c;不同于线性结构&…...

虚拟化技术 — VirtIO 虚拟设备接口标准

目录 文章目录 目录VirtIOVirtIO 虚拟设备接口标准VirtIO 的前后端分层架构标准VirtIO 的数控路径分离架构标准VirtIO 的传输层标准VirtIO 标准在 Linux 中的实现VirtIO VirtIO 由 Rusty Russell 开发,最初是为了支持自己开发的 lguest Hypervisor,其设计目标是在虚拟化环境…...

Dubbo——SpringBoot集成Dubbo(@Autowired和@Reference的区别、Dubbo的服务治理)

Dubbo——原生API实现远程调用_Strine的博客-CSDN博客 在上一篇文章中我们讲了如何使用原生API发起远程调用&#xff0c;显然这种方式肯定是非常麻烦的&#xff0c;因此我们这里就讲如何使用SpringBoot去集成Dubbo将这些配置简化。 生产者服务 添加配置文件 dubbo:applicat…...

高并发系统的三把利器

目录 1.限流 2.缓存 2.1.缓存的使用场景 3.降级 3.1.什么是降级&#xff1f; 3.2.服务降级方式 4.其他高并发手段 4.1. 集群 4.2.拆分 4.2.1 应用拆分 4.2.2 数据库 4.3. 静态化 4.4.削峰 4.5.限流 5.总结 参考 保护高并发系统的三大利器&#xff1a;限流、熔…...

AppiumWinAppDriver自动化测试 Failed to locate opened application window with appid问题

问题产生原因&#xff1a;1.期望能力选项参数丢失 例如&#xff1a;capabilities.setCapability("appWorkingDir", "C:\\Program Files (x86)\\Tencent\\app")) 某些app需要设置目录属性才可以启动。 问题产生原因&#xff1a;2.访问权限不足 例如&…...

渗透测试--6.1.aircrack-ng破解wifi密码

目录 1.Aircrack-ng简介 1.1 airdump-ng 1.2 aireplay-ng 1.3 aircrack-ng 2.Deauth攻击 3.aircrack-ng工具破解无线网络密码 步骤一&#xff1a;虚拟机连接实验需要用到的网卡 步骤二&#xff1a;设置网卡为监听模式 步骤三&#xff1a;使用wlan0mon网卡扫描附近wif…...

C++中的继承、以及赋值兼容转换。

一、继承的概念及定义 继承可以使代码复用&#xff0c;允许在保持原有类特性的基础上进行扩展。 举个例子&#xff1a;就好比我现在要封装老师、学生等这些人的属性和方法&#xff0c;但是这些人都有重复的属性和方法&#xff0c;比如name、age、sex等等&#xff0c;那么我可…...

js浏览器实现简单的实时扫一扫功能

描述&#xff1a;利用vue-qrcode-reader插件实现h5/wap端简单的扫一扫功能 参考文档&#xff1a;https://gruhn.github.io/vue-qrcode-reader/demos/Validate.html官方文档 安装插件 npm i --save vue3-qr-reader 或 yarn add vue3-qr-reader 注意项目运行必须在https下&…...

unity愤怒的小鸟学习制作(二)

终于又开始了啦啦啦&#xff0c;我有一个自己的相机了&#xff0c;真开心&#xff0c;诶嘿 视频链接和素材如下&#xff1a;视频 小鸟的飞出 想要让小鸟在拉开弹弓之后能飞出去&#xff0c;就必须让这个组件失活&#xff0c;如下 所以我们更改脚本内容&#xff0c;加入&#…...

干外包3年,彻底寄了...

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了6年的功能测试&…...

软考高项论文范文(三)

论信息系统项目的沟通管理 【摘要】&#xff08;该摘要共313个字符&#xff09; 本文讨论了ⅹⅹ省社保系统民政统一软件开发项目的沟通管理。该项目是在国家大社会保险政策指导下于2018年10月份正式启动的。该系统为用户提供了优抚安置、救灾救济等十大主要业务功能。在本文中…...

浅谈谈谈OTA召回2023

近日&#xff0c;国家市场监督管理总局发布特斯拉召回公告&#xff0c;一下子掀起了互联网热议&#xff0c;这次召回的范围是在2019年1月12日至2023年4月24日期间国内销售特斯拉汽车&#xff08;含国产和进口共计110万辆车&#xff09;&#xff0c;在这个召回公告中有两点值得关…...

【GDI+】旋转文本/斜体字

一、需求 想要绘制如下所示的斜体字&#xff0c;45度 二、分析&思路 Graphics类有个 RotateTransform方法&#xff0c;可以传入任意角度的值来旋转画板。但是这个方法的旋转中心是画板的左上角&#xff0c;所以直接单单用这个方法不能满足我们的需求。此外&#xff0c; G…...

python3 面试题总结

Python global 语句的作用lambda 匿名函数好处Python 错误处理Python 内置错误类型简述 any() 和 all() 方法Python 中什么元素为假&#xff1f;提高 Python 运行效率的方法Python 单例模式为什么 Python 不提供函数重载实例方法/静态方法/类方法__new__和 __init __方法的区别…...

select poll epoll有什么区别

select/poll select 实现多路复用的方式是&#xff0c;将已连接的 Socket 都放到一个文件描述符集合&#xff0c;然后调用 select 函数将文件描述符集合拷贝到内核里&#xff0c;让内核来检查是否有网络事件产生&#xff0c;检查的方式很粗暴&#xff0c;就是通过遍历文件描述…...

Java基础面试题突击系列1

&#x1f469;&#x1f3fb; 作者&#xff1a;一只IT攻城狮 &#xff0c;关注我不迷路 ❤️《java面试核心知识》突击系列&#xff0c;持续更新… &#x1f490; 面试必知必会学习路线&#xff1a;Java技术栈面试系列SpringCloud项目实战学习路线 &#x1f4dd;再小的收获x365天…...

go-zero和dtm分布式事务实现

go-zero是一个基于Go语言的微服务开发框架&#xff0c;而DTM&#xff08;Distributed Transaction Manager&#xff09;是一个分布式事务管理器&#xff0c;用于实现跨多个微服务的分布式事务。 下面是使用go-zero和DTM实现分布式事务的基本步骤&#xff1a; 安装和配置DTM&am…...

Springboot +Flowable,会签、或签简单使用(一)

一.简介 **会签&#xff1a;**在一个流程中的某一个 Task 上&#xff0c;这个 Task 需要多个用户审批&#xff0c;当多个用户全部审批通过&#xff0c;或者多个用户中的某几个用户审批通过&#xff0c;就算通过。 例如&#xff1a;之前的请假流程&#xff0c;假设这个请假流程…...

银行面试中的即兴演讲技巧,你了解吗

面试的主要形式有无领导小组讨论、结构化和半结构化面试&#xff0c;一些银行还会出现辩论赛、角色扮演、即兴演讲等形式&#xff0c;今天小编就来聊一聊面试中的即兴演讲&#xff0c;从如信银行考试中心了解到&#xff1a; 简单来说即兴演讲就是在特定情境下&#xff0c;自发或…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

Docker 运行 Kafka 带 SASL 认证教程

Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明&#xff1a;server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...