C#文本解析

文本解析有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文件要大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值