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驅動的時候就全部加載到內存中了。

上面的執行結果應該跟之前的類似。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM