读取配置文件等对于一个游戏的重要性不需要多说,本文总结了本人最近经常用到的C#解析文本文件的方法。本文作为一个涂鸦,仅仅用于提供几个解决问题的思路,对于代码是否高雅等问题不予考虑。

准备工作

创建一个类,用于保存单个Site信息。

public class Site  {
	public string Name{get;set;}
	public string Url{ get; set;}
}

创建一个类,用于保存Site类数组。

public class SitesList {
        public Site[] sites;
}

创建一个脚本,名称随意,Start方法中写初始化路径代码(下文所提的初始内容即为此):

//Application.dataPath,unity中用来获取Assets路径的属性
string path = Application.dataPath + "/Resources/";
string jsonName = "Sites.json";
string txtName = "Sites.txt";
string xmlName = "Sites.xml";
string jsonPath = path + jsonName;
string txtPath = path + txtName;
string xmlPath = path + xmlName;

TXT文件的存储与解析

TXT保存

思路:将类手动转换成字符串,拼串,保存至文件中。
代码:

public void TxtToFile(SitesList sitesList,string filePath)
        {
                string str = "Name|Url" + '\n';
                for (int i = 0; i < sitesList.sites.Length; i++) {
                        str += sitesList.sites[i].Name
                                + '|' 
                                + sitesList.sites[i].Url 
                      //最后一行不用追加换行
                                +  (i == sitesList.sites.Length - 1 ? "": "\n");
                }
                FileStream fs = File.Open (filePath, FileMode.Create);
                StreamWriter sw = new StreamWriter (fs);
                sw.Write (str);
                sw.Flush ();
                sw.Close ();
                fs.Close ();
                Debug.Log ("保存成功");
        }

start中追加如下内容:

Site s1 = new Site (){ Name = "梓喵出没",Url ="http://www.azimiao.com"};
Site s2 = new Site (){ Name = "Xema", Url = "https://www.xema.ink" };
Site s3 = new Site (){ Name ="Pret",Url = "https://www.pret-page.com"};
SitesList siteList = new SitesList ();
siteList.sites = new Site[]{ s1,s2,s3};
TxtToFile (siteList, txtPath);

unity中创建一个Cube(随意),将该脚本挂载到该游戏对象中,点击运行。
效果如图:

保存文件的内容为:

Name|Url
梓喵出没|http://www.azimiao.com
Xema|https://www.xema.ink
Pret|https://www.pret-page.com

TXT读取与格式化

思路:读取文件中所有内容,按换行符号’\n’切割字符串,获取的字符串数组每个元素即为一个Site对象。按照标识符分隔对象字符串(这里使用的是’|’),创建对象分别赋值即可。
代码:

public void TxtToClass(out SitesList rec,string filePath)
	{
		rec = new SitesList ();
		if (!File.Exists(filePath)) {
			Debug.Log ("文件不存在");
			return;
		}
		FileStream fs = File.Open (filePath, FileMode.Open);
		StreamReader sr = new StreamReader (fs);
		string txtData = sr.ReadToEnd ();
		//切割每一行
		string[] lineData = txtData.Split ('\n');
		//容器内数组初始化
		rec.sites = new Site[lineData.Length -1];
		for (int i = 1; i < lineData.Length; i++) {
			int index = 0;
			//切割元素字符串
			string[] siteTemp = lineData [i].Split ('|');
			//给容器内数组赋值
			rec.sites [i - 1] = new Site (){Name =siteTemp[index++],Url = siteTemp[index++] };
		}
	}

start中追加如下内容(初始内容追加,下同):

SitesList siteList = new SitesList ();
TxtToClass (out siteList, txtPath);
                foreach (Site item in siteList.sites) {
                        Debug.Log (item.Name + "|" + item.Url);
                }

运行结果:

TXT更新

txt文件没有节点一说,也就没有修改某节点局部更新的方法,因此需要拼接新的字符串覆盖原内容。这与保存内容一致,因此不再重复。

JSON文件的存储与解析

额外准备工作:需要导入LitJSON.dll并引用其命名空间:

using LitJson;

JSON保存

思路:先将Site类格式化为Json字符串,然后检查文件是否存在(覆盖or创建),最后保存字符串。
代码:

 //将类转化为Json对象
public void SiteToJson(SitesList siteList,string filePath)
{
        string jsonData = JsonMapper.ToJson (siteList);

        //可以不写,pen方法会根据参数自动处理
        if (!File.Exists(filePath)) {
                //文件不存在则创建新文件
                FileStream fstemp = File.Create (filePath);
                fstemp.Close ();
                Debug.Log ("文件不存在,已创建新文件");
        }
        //打开文件流,Create模式表示如果不存在则创建,如果存在则覆盖原内容
        FileStream fs = File.Open (filePath, FileMode.Create);
        //创建StreamWriter
        StreamWriter sw = new StreamWriter (fs,System.Text.Encoding.UTF8);
        sw.Write (jsonData);
        //清空缓冲区,确保写入
        sw.Flush ();
        //关闭StreamWriter
        sw.Close ();
        //关闭文件流
        fs.Close ();
        Debug.Log ("写入完成");
}

start中追加如下内容(初始内容追加,下同):

Site s1 = new Site (){ Name = "梓喵出没",Url ="http://www.azimiao.com"};
Site s2 = new Site (){ Name = "Xema", Url = "https://www.xema.ink" };
Site s3 = new Site (){ Name ="Pret",Url = "https://www.pret-page.com"};
siteList.sites = new Site[]{ s1,s2,s3};
SiteToJson (siteList, jsonPath);

运行效果:

打开创建的Json文件,发现添加的内容为(原内容无换行,为了美观手动添加了换行):

{
	"sites":
	[
	{"Name":"\u6893\u55B5\u51FA\u6CA1","Url":"http://www.azimiao.com"},
		{"Name":"Xema","Url":"https://www.xema.ink"},
		{"Name":"Pret","Url":"https://www.pret-page.com"}
	]
}

JSON读取与格式化

思路:先读取文件中所有字符,然后将其转化成Json字符串,最后将其解析为对象。
代码:

//将Json转化为类
        public void ParseXml(out SitesList rec,string filePath)
        {
                if (!File.Exists(filePath)) {
                        Debug.LogWarning (filePath +"不存在");
                        return;
                }
                //FileMode.Open,打开已经存在的文件,如果不存在则抛出文件不存在异常
                FileStream fs = File.Open (filePath,FileMode.Open);
                StreamReader sr = new StreamReader (fs);
                string data = sr.ReadToEnd ();

                rec = JsonMapper.ToObject<SitesList> (data);
                //关闭流
                sr.Close ();
                //关闭流
                fs.Close ();
                Debug.Log ("读取完成");
        }

start中追加如下内容(初始内容追加,下同):

 SitesList siteList;
  ParseXml (out siteList, jsonPath);
  foreach (Site item in siteList.sites) {
                   Debug.Log (item.Name+"|"+item.Url);

}

运行结果:

更新

不写,原因同TXT。

XML

Xml美滋滋美滋滋。
准备工作:
引用命名空间:

using System.Xml;

创建一个xml文件,包含xml头及根节点:

<?xml version="1.0" encoding="UTF-8" ?>
<Sites></Sites>

XML添加与保存

思路:获取xml根节点,向xml根节点插入子节点,最后保存即可。
代码:

public void ClassToXml(SitesList sitesList,string filePath)
	{
		XmlDocument doc = new XmlDocument ();
		//加载文件
		doc.Load (filePath);
		//获取根节点Sites
		XmlNode root = doc.SelectSingleNode ("Sites");
		foreach (Site item in sitesList.sites) {
                        XmlElement site = doc.CreateElement("Site");
			XmlElement name = doc.CreateElement ("Name");
			name.InnerText = item.Name;
			XmlElement url = doc.CreateElement ("Url");
			url.InnerText = item.Url;
			//添加子节点
			site.AppendChild (name);
			site.AppendChild (url);
			root.AppendChild (site);
		}
		//保存文件
		doc.Save (filePath);
	}

start中追加如下内容(初始内容追加,下同):

Site s1 = new Site (){ Name = "梓喵出没",Url ="http://www.azimiao.com"};
Site s2 = new Site (){ Name = "Xema", Url = "https://www.xema.ink" }; 
Site s3 = new Site (){ Name ="Pret",Url = "https://www.pret-page.com"};
SitesList siteList = new SitesList ();
siteList.sites = new Site[]{ s1,s2,s3};
ClassToXml(siteList,xmlPath);

运行结果:
打开原xml可见添加内容如下:

XML读取与解析

思路:获取根节点Sites,循环遍历根节点获取每个子节点Site,通过Site中的Name节点与Url节点的innerText创建对象。
代码:

public void XmlToClass(out SitesList rec, string filePath)
        {
		XmlDocument doc = new XmlDocument ();
		doc.Load (filePath);
		XmlNode root = doc.SelectSingleNode ("Sites");
		XmlNodeList xmlSites = root.SelectNodes ("Site");
		rec = new SitesList ();
		rec.sites = new Site[xmlSites.Count];
		int index = 0;
		foreach (XmlNode item in xmlSites) {
			string name = item ["Name"].InnerText;
			string url = item ["Url"].InnerText;
			Site temp = new Site (){ Name = name, Url = url };
			rec.sites [index] = temp;
			index++;
		}

在Start中追加如下内容:

SitesList siteList = new SitesList ();
XmlToClass (out siteList, xmlPath);
                foreach (Site item in siteList.sites) {
                        Debug.Log (item.Name + "|" + item.Url);
                }

运行结果:
如下图所示:

XML更新

思路:通过条件语句获取节点对象,修改innerText的值,最后保存即可。可通过上文略加修改实现。

XML删除某节点

使用doc.RemoveChild(XmlNode oldNode)即可。

总结

相对于TXT与JSON,XML更易实现局部更新。通过这几个小例子,能够掌握简单的文件读写即文件序列化与反序列化方法。

引用资料

1、[头图]【Unity】Unity-Japan UnityChanSD角色

我来吐槽

*

*

3位绅士参与评论

  1. c0smxsec10-22 15:49 回复

    你 老司机 做游戏

  2. answer10-19 10:19 回复

    汪汪汪~ 加友链啦~
    answer:www.traceback.cc

  3. 北海10-18 21:00 回复

    emmm 大大大大佬 那个邮件通知的插件一直发送失败怎么破呀?