文本解析有3种,分别为:XML解析,JSON解析和Excel解析
一 XML解析
XML解析,可以细分为两种,一种是子节点的字段值较多,另一种是子节点的属性较多。本文会通过具体示例来详细讲述以上两种的适用场景。
下面现在第一种,子节点的字段值较多的。解析示例:如解析下述XML文件。
被解析的xml文件:
<skills>
<skill>
<id>2</id>
<name lang ="cn">天下无双</name>
<damage>123</damage>
</skill>
<skill>
<id>3</id>
<name lang ="cn">永恒零度</name>
<damage>90</damage>
</skill>
<skill>
<id>4</id>
<name lang="cn">咫尺天涯</name>
<damage>400</damage>
</skill>
</skills>
解析思想:利用位于System.Xml下的xml解析类XmlDocument。首先获取根节点,然后根据根节点获取其所有的子节点集合。再获取每个子节点的字段值。比如:示例中的,首先获取skills结点,然后再获取它的子节点skill,最后根据子节点依次获取id、name、damage等字段值。
具体解析逻辑代码如下:
class Program
{
static void Main(string[] args)
{
//创建技能信息集合,用来存储技能
List<Skill> skillList = new List<Skill>();
//XmlDocument专门用来解析xml文档
XmlDocument xmlDoc = new XmlDocument();
//选择要加载解析的xml文档的名字
//xmlDoc.Load("skillInfo.xml");//第一种加载方式
//第二种加载方式 传递一个字符串(xml格式的字符串)
xmlDoc.LoadXml(File.ReadAllText("skillInfo.xml"));
//得到根结点
XmlNode rootNode = xmlDoc.FirstChild;//获取第一个结点
//得到根结点下面的子结点的集合
XmlNodeList skillNodeList =rootNode.ChildNodes;//获取当前节点下面的所有子节点
foreach (XmlNode skillNode in skillNodeList)
{
Skill skill = new Skill();//利用每个Skill结点创建一个对象
XmlNodeList fieldNodeList = skillNode.ChildNodes;//获取skill结点下面所有的结点
foreach (XmlNode fieldNode in fieldNodeList)
{
//通过Name属性 可以获取一个结点的名字
if (fieldNode.Name == "id")
{
int id = Int32.Parse(fieldNode.InnerText);//获取结点内部的文本
skill.Id = id;
}
else if (fieldNode.Name == "name")
{
string name = fieldNode.InnerText;
skill.Name = name;
skill.Lang = fieldNode.Attributes[0].Value;//获取属性值
}
else if (fieldNode.Name == "damage")
{
skill.Damage = Int32.Parse(fieldNode.InnerText);
}
}
skillList.Add(skill);
}
foreach (var skill in skillList)
{
//此处,需要自己重写Skill类的ToString方法
Console.WriteLine(skill.ToString());
}
Console.ReadKey();
}
}
再看看第二种,子节点属性值较多时如何解析。解析示例如下:
<SkillInfo>
<SkillList>
<Skill
SkillID="20002"
SkillEngName="Smash"
TriggerType="1"
ImageFile="data/gfx/image/gui_icon_skill_000.dds"
AvailableRace="7"
>
<Name>重击</Name>
</Skill>
<Skill
SkillID="20003"
SkillEngName="Hide"
TriggerType="2"
ImageFile="data/gfx/image/gui_icon_skill_001.dds"
AvailableRace="1"
>
<Name>隐身</Name>
</Skill>
<Skill
SkillID="20004"
SkillEngName="Ikari"
TriggerType="3"
ImageFile="data/gfx/image/gui_icon_skill_002.dds"
AvailableRace="1"
>
<Name>怒之翼</Name>
</Skill>
<Skill
SkillID="20005"
SkillEngName="Revenge"
TriggerType="5"
ImageFile="data/gfx/image/gui_icon_skill_003.dds"
AvailableRace="2"
>
<Name>光之复仇</Name>
</Skill>
</SkillList>
</SkillInfo>
解析思想:首先还是获取根节点,然后根据根节点获取属性上层的父节点集合,然后通过遍历,利用XmlNode类的Attributes属性获取每层遍历的属性集合。再通过XmlAttributeCollection 类的字符串索引器,依次获取每个属性值。
具体解析逻辑代码如下:
class Program
{
static void Main(string[] args)
{
List<Skill> skillList = new List<Skill>();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("xml技能信息.txt");
//获取根结点
XmlNode skillInfoNode = xmlDoc.FirstChild;
XmlNode skillListNode = skillInfoNode.FirstChild;
//获取属性父节点集合
XmlNodeList skilNodeList = skillListNode.ChildNodes;
//通过遍历获取每个属性的父节点
foreach (XmlNode skillNode in skilNodeList)
{
Skill skill = new Skill();
//用索引器获取同级字段值
XmlElement ele = skillNode["Name"];
skill.Name = ele.InnerText;
//获取该结点字段属性集合
XmlAttributeCollection col = skillNode.Attributes;
//通过字符串索引器获取一个属性对象
skill.Id = Int32.Parse(col["SkillID"].Value);
skill.EngName = col["SkillEngName"].Value;
skill.TriggerType = Int32.Parse(col["TriggerType"].Value);
skill.ImageFile = col["ImageFile"].Value;
skill.AvailableRace = Int32.Parse(col["AvailableRace"].Value);
skillList.Add(skill);
}
foreach (var skill in skillList)
{
//同上
Console.WriteLine(skill);
}
Console.ReadKey();
}
}
二 JSON解析
要使用JSON解析,需要引入JSON库。引入JSON库有两种方式:(1)方式1:首先,在官网上下载Json库文件(http://lbv.github.io/litjson/)LitJson.dll,然后将其复制到VS项目工程。再手动添加引用。在引用文件夹上,右键,选择添加引用,再选择浏览,找到LitJson.dll文件。添加到项目即可。(2)如果,你采用VS 2012以上版本开发项目的话,可以在工程界面,在“引用”上右键,打开管理netget程序包,在联机里面搜索litjson 在搜索结果中选择一个点击安装,它会自动将LitJson.dll文件添加到引用。
JSON解析也可以分为两种,第一种使用JsonMapper去解析json文本;第二种使用泛型解析。当使用泛型解析时,需要注意,json文件对象的键要与定义Skill类的字段名要保持一直,否则解析不成功。
下面看第一种解析方式,解析示例如下:
技能信息.txt
[
{"id":2,"name":"天下无双","damage":123},
{"id":3,"name":"天下无贼","damage":21},
{"id":4,"name":"咫尺天下","damage":900}
]
第一种方式解析思想:先讲文件转换成JsonData(集合)对象,再通过遍历获取每一个对象,最后通过字符串索引器可以取得键值对的值。效果如图1。
逻辑代码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LitJson;
namespace _020_json操作
{
class Program
{
static void Main(string[] args)
{
List<Skill> skillList = new List<Skill>();
//使用jsonMapper去解析json文本
//jsondata代表一个数组或者一个对象,主要取决于json里面是什么
JsonData jsonData =JsonMapper.ToObject(File.ReadAllText("技能信息.txt"));
foreach (JsonData temp in jsonData) //在这里temp代表一个对象
{
Skill skill = new Skill();
JsonData idValue = temp["id"]; //通过字符串索引器可以取得键值对的值
JsonData nameValue = temp["name"];
JsonData damageValue = temp["damage"];
int id = Int32.Parse(idValue.ToString());
string name = nameValue.ToString();
int damage = Int32.Parse(damageValue.ToString());
skill.id = id;
skill.damage = damage;
skill.name = name;
skillList.Add(skill);
}
foreach (var temp in skillList)
{
Console.WriteLine(temp);
}
Console.ReadKey();
}
}
}
下面看第二种方式解析上述文件,解析思想:首先将json文件的键与对象的属性一一对应,再通过JsonMapper.ToObject<>()方法来获取。尖括号里面是一个泛型,传入的参数是什么类型,返回值则就是什么类型。
逻辑代码如下:
Program.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LitJson;
namespace _020_json操作
{
class Program
{
static void Main(string[] args)
{
//2.使用泛型解析(json文件对象的键要与定义Skill类文件的字段名要保持一致,否则解析不成功)
//Skill[] skillArray = JsonMapper.ToObject<Skill[]>(File.ReadAllText("技能信息.txt"));
//foreach (var temp in skillArray)
//{
// Console.WriteLine(temp);
//}
List<Skill> skillList = JsonMapper.ToObject<List<Skill>>(
File.ReadAllText("技能信息.txt"));
foreach (var temp in skillList)
{
Console.WriteLine(temp);
}
Console.ReadKey();
}
}
}
Skill.cs
class Skill
{
public int id; //此处字段,一定要与被解析的json文件的键一致,否则会导致解析失败
public int damage;
public string name;
public override string ToString()
{
return string.Format("Id: {0}, Damage: {1}, Name: {2}",id,damage,name);
}
}
再看看一个比较复杂的解析例子。
主角信息.txt
{
"Name":"lYl",
"Level":99,
"Age":18,
"SkillList":[
{"id":2,"name":"天下无双","damage":123},
{"id":3,"name":"天下无贼","damage":21},
{"id":4,"name":"咫尺天下","damage":900}
]
}
解析分析:首先把它整体看作一个对象。即一个Player对象,所以对应生成一个Player类。再看这个对象包括四个属性,分别为:Name,Level,Age,SkillList属性。其中SkillList属性包括一个数组对象。因此,生成一个Skill类,来对应数组元素。该数组中的元素,即一个Skill对象,该对象又包括三个属性,分别为:id,name,damage.思路清楚了,方法同上。效果如图2,逻辑代码如下:
Player.cs
class Player
{
//public string name;//字段或者属性名要跟json里面(主角信息)的对应,且需要public类型
//public int level;
public string Name { get; set; }
public int Level { get; set; }
public int Age { get; set; }
public List<Skill> SkillList { get; set; }
public override string ToString()
{
//List集合需要单独输出
return string.Format("Name: {0}, Level: {1}, Age: {2}",Name,Level,Age);
}
}
class Program
{
static void Main(string[] args)
{
Player p = JsonMapper.ToObject<Player>(File.ReadAllText("主角信息.txt"));
Console.WriteLine(p);
foreach (var temp in p.SkillList)
{
Console.WriteLine(temp);
}
Console.ReadKey();
}
}
还有一个Skill类,与上述Skill.cs一致,在此不再赘述。此外,大部分语言都支持JSON。它广泛运用于数据交换。例如,基于上述例子,它可以将一个Player对象,以一个字符串的形式发送出去,很是方便。效果如图3,代码示例如下:
class Program
{
static void Main(string[] args)
{
//将一个player对象转换成一个json
Player p = new Player();
p.Name = "花千骨";
p.Level = 100;
p.Age = 16;
Skill ss = new Skill();
ss.id = 1;
ss.name = "葵花宝典";
ss.damage = 200;
p.SkillList=new List<Skill>();
p.SkillList.Add(ss);
string json = JsonMapper.ToJson(p);
Console.WriteLine(json);
Console.ReadKey();
}
}
上述JSON程序运行的截图如下:
图1
图2
图3
三 Excel解析
Excel解析基于using System.Data.OleDb,解析思想:将Excel文件作为一个数据源进行解析读取。由于Excel涉及两个版本,一个以xls结尾的旧版,一个以xxl结尾的新版,分别对应的连接字符串为:
(1)xls版本:
string connectString = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + fileName +
";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\"";
(2)xxl版本
string connectString = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + fileName + ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\"";
解析示例如图四:
图4
解析思想:首先创建一个OleDbConnection的连接到数据源的对象,打开连接,再创建适配器与数据集,将适配器中的数据填充到数据集中,再关闭数据源连接。通过数据集的Tables属性,取出数据集中的所有表格。选择表格集合,将表格集合的表格元素取出,存放在DataTable中。在通过table的Rows属性,取出表格的行集合。最后通过遍历,取出每个行的子元素。效果如图5,具体逻辑代码如下:
class Program
{
static void Main(string[] args)
{
string fileName = "装备信息.xls";
string connectString = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source="
+ fileName + ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\"";
//创建连接到数据源的对象
OleDbConnection connection = new OleDbConnection(connectString);
//打开连接
connection.Open();
string sql = "select * from [Sheet1$]";//查询表格1
//创建适配器对象,用sql、connection来创建
OleDbDataAdapter adapter = new OleDbDataAdapter(sql,connection);
DataSet dataSet = new DataSet();//用来存放数据,用来存放DataTable
adapter.Fill(dataSet);//表示把查询的结果放到填充dataSet里面
connection.Close();//查询完毕后,释放连接资源
//取得数据
DataTableCollection tableCollection = dataSet.Tables;//获取当前集合中所有的表格
//因为我们只往dataset里面放置了一张表格,所以这里取得索引为0的表格就是我们刚刚查询到的表格
DataTable table = tableCollection[0];
//取得表格当中的数据
//取得table中所有的行
DataRowCollection rowCollection = table.Rows;//返回了行的集合
//遍历行的集合,取得每一个行datarow对象
foreach (DataRow row in rowCollection)
{
//取得row中的前8列数据 索引0-7
for (int i = 0; i < 8; i++)
{
Console.Write(row[i] + " ");
}
Console.WriteLine();
}
Console.ReadKey();
}
}
实际运行截图:
图5
四 小结
文本解析无论是哪一种,一般都是根据自己的需求来决定的。但最常用的还是JSON格式的解析,多用于数据交互。Excel解析,可用于游戏开发时,方便游戏策划调整数据。但有一点需要指出,就是同等数据传输的话,XML文件要比JSON文件要大。