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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | /// <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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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)销毁。
所以定义一个接口:
1 2 3 4 5 | public interface IClientData { bool Load(); void Destroy(); } |
让所有的数据类都实现这个接口,然后在搞个数据管理器(单例),在Init里面加载所有的数据类,就拿ServerData来演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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驱动的时候就全部加载到内存中了。
上面的执行结果应该跟之前的类似。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步