Unity3d通用工具类之数据配置加载类-ini配置文件加载
Unity3d通用工具类之数据配置加载类-ini配置文件加载
上次我们讲过xml文件的加载配置管理,今天我们换个配置文件,也是比较常见的配置文件.ini格式的数据。
按照国际管理先贴一张啥是.ini文件:
这里我们分类下,总的来说.ini文件就是里面保存多有数据的头,他的下面包含与之相关的字段数据(采用key-value格式)。
ok,知道格式之后,我们写个IniFile数据管理类:
首先,我们定义他有哪些接口:
肯定他需要加载一个配置文件,那么就定义:
1.public void LoadFromFile(string fileName)
还有我们需要取得某个头部下面的key的value,那么就需要定义:
2.public string GetValue(string sectionName, string key, string defaultValue)
sectionName代表的是头部名称,key代表键值,value代表对应这个键值的值,如果没有发现这个key,就返回默认的值defaultValue。
因为一个配置文件有多个头部,那么我们就需要定义一个头部类来管理,符合类的单一职责。
所以这里得在定义一个IniSection头部类。
他包含哪些数据:
1.头部名称:
private string sectionName;
2.键值对:
private Dictionary<string, string> m_dicKeyValue;
在IniFile类里面维护一个头部列表缓存:
3.private List<IniSection> m_sectionList;
在从文件中加载的时候初始化他,也就是LoadFromFile()方法里面,初始化所有头部的数据。
IniFile.cs:
public class IniFile { private List<IniSection> m_sectionList; public IniFile() { m_sectionList = new List<IniSection>(); } public void LoadFromFile(string fileName) { string strFullPath = Application.dataPath + "/" + fileName; if (!File.Exists(strFullPath)) { return; } using (FileStream fs = new FileStream(strFullPath, FileMode.Open)) { LoadFromStream(fs); } } /// <summary> /// 取得配置文件中所有的头名称 /// </summary> /// <returns></returns> public List<string> GetAllSectionName() { List<string> sectionList = new List<string>(); foreach (var sec in m_sectionList) { sectionList.Add(sec.SectionName.ToLower()); } return sectionList; } /// <summary> /// 取得头部相关的value /// </summary> /// <param name="sectionName"></param> /// <param name="key"></param> /// <param name="defaultValue"></param> /// <returns></returns> public string GetValue(string sectionName, string key, string defaultValue) { IniSection section = GetSection(sectionName); if (section != null) { return section.GetValue(key, defaultValue); } return defaultValue; } private void LoadFromStream(FileStream fs) { using (StreamReader sr = new StreamReader(fs)) { m_sectionList.Clear(); string line = null; IniSection section = null; int equalSignPos = 0;//=号的标记的位置 string key, value; while (true) { line = sr.ReadLine(); if (null == line) { break; } line = line.Trim(); if (line == "") { continue; } //跳过注释 if (line.Length >= 2 && line[0] == '/' && line[1] == '/') { continue; } if (line[0] == '[' && line[line.Length - 1] == ']') { //移除首尾的'[]' line = line.Remove(0, 1); line = line.Remove(line.Length - 1, 1); //去SectionList缓存中找是否存在这个Section section = GetSection(line); //如果没有找到就直接new一个 if (null == section) { section = new IniSection(line); m_sectionList.Add(section); } } else { //就是在这个头下面的数据字段,key-value格式 equalSignPos = line.IndexOf('='); if (equalSignPos != 0) { key = line.Substring(0, equalSignPos); value = line.Substring(equalSignPos + 1, line.Length - equalSignPos - 1); section.AddKeyValue(key, value); } else { Debug.LogWarning("value为空"); } } } } } /// <summary> /// 从缓存中找Section /// </summary> /// <param name="sectionName"></param> /// <returns></returns> private IniSection GetSection(string sectionName) { foreach (var section in m_sectionList) { if (section.SectionName.ToLower() == sectionName.ToLower()) { return section; } } return null; } }
IniSection.cs:
/// <summary> /// ini头部+数据 /// </summary> public class IniSection { private string sectionName; private Dictionary<string, string> m_dicKeyValue; public string SectionName { get { return this.sectionName; } set { this.sectionName = value; } } public IniSection(string name) { this.sectionName = name; this.m_dicKeyValue = new Dictionary<string, string>(); } /// <summary> /// 添加key-value的值 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void AddKeyValue(string _key,string _value) { string value = null; if (m_dicKeyValue.TryGetValue(_key, out value)) { if (value != null) { m_dicKeyValue[_key] = _value; } } else { m_dicKeyValue.Add(_key, _value); } } /// <summary> /// 根据key取得value,如果没有取到就返回默认的值 /// </summary> /// <param name="key"></param> /// <param name="defaultValue"></param> /// <returns></returns> public string GetValue(string key, string defaultValue) { string value = null; m_dicKeyValue.TryGetValue(key, out value); if (m_dicKeyValue.TryGetValue(key, out value)) { return value; } return defaultValue; } }
Ok,我们进行下测试,写个ServerData.cs类,继承MonoBehavior:
using UnityEngine; using System.Collections; public class ServerData : MonoBehaviour { public string m_cfgName = "Server.ini"; public void Load() { IniFile ini = new IniFile(); ini.LoadFromFile(m_cfgName); foreach (var name in ini.GetAllSectionName()) { if (string.Equals(name, "serverinfo")) { Debug.Log(ini.GetValue(name, "IP", "")); } } } public void Start() { Load(); } }
可以看到在Console中打印出配置文件的数据:
这个数据类我写的有问题,这里只是我测试用的,按正常的开发是不能继承mono,因为每个数据类都需要Load,还有会有Destory(Dispose)销毁。
所以定义一个接口:
public interface IClientData { bool Load(); void Destroy(); }
让所有的数据类都实现这个接口,然后在搞个数据管理器(单例),在Init里面加载所有的数据类,就拿ServerData来演示:
using UnityEngine; using System.Collections; public class ServerData : IClientData { public string m_cfgName = "Server.ini"; public bool Load() { IniFile ini = new IniFile(); ini.LoadFromFile(m_cfgName); foreach (var name in ini.GetAllSectionName()) { if (string.Equals(name, "serverinfo")) { Debug.Log(ini.GetValue(name, "IP", "")); } } return true; } public void Destroy() { } }
ClientDataManager.cs:
using UnityEngine; using System.Collections; public class ClientDataManager { private static ClientDataManager m_oInstance; public static ClientDataManager Instance { get { if (m_oInstance == null) { m_oInstance = new ClientDataManager(); } return m_oInstance; } } public ServerData ServerData; public ClientDataManager() { ServerData = new ServerData(); } public void Init() { ServerData.Load(); } }
Ok,搞个驱动类:Driver.cs:
using UnityEngine; using System.Collections; public class Driver : MonoBehaviour { // Use this for initialization void Start () { ClientDataManager.Instance.Init(); } // Update is called once per frame void Update () { } }
这样,我们假如说在ClientDataManager里面添加所有的数据类,他直接在Driver驱动的时候就全部加载到内存中了。
上面的执行结果应该跟之前的类似。