1. 程式人生 > >Unity_ini配置檔案應用(用於讀取或寫入程式設定)

Unity_ini配置檔案應用(用於讀取或寫入程式設定)

public static class IniSetting
{
    private static string mINIFileName = Application.dataPath + "/../config.ini";

    public enum SectionName
    {
        config,//瀏覽
        config2,//共享記憶體
    }

    public static bool GetBool(string Key, SectionName section = SectionName.config, bool defaultValue = false)
    {
        bool value = defaultValue;
        string sectionName = section.ToString();

        Action<INIParser> action =
            (ini) =>
            {
                if (!ini.IsKeyExists(sectionName, Key))
                    ini.WriteValue(sectionName, Key, defaultValue);
                value = ini.ReadValue(sectionName, Key, defaultValue);
            };
        OpenAndReadINI(mINIFileName, action);
        Debug.LogWarning(Key + "  " + value);
        return value;
    }


    public static string GetString(string Key, SectionName section = SectionName.config, string defaultValue = "")
    {
        string value = defaultValue;
        string sectionName = section.ToString();

        Action<INIParser> action =
            (ini) =>
            {
                if (!ini.IsKeyExists(sectionName, Key))
                    ini.WriteValue(sectionName, Key, defaultValue);
                value = ini.ReadValue(sectionName, Key, defaultValue);
            };

        OpenAndReadINI(mINIFileName, action);
        return value;
    }

    public static float GetFloat(string Key, SectionName section = SectionName.config, float defaultValue = 0)
    {
        float value = defaultValue;
        string sectionName = section.ToString();

        Action<INIParser> action =
            (ini) =>
            {
                if (!ini.IsKeyExists(sectionName, Key))
                    ini.WriteValue(sectionName, Key, defaultValue);
                value = (float)ini.ReadValue(sectionName, Key, defaultValue);
            };
        OpenAndReadINI(mINIFileName, action);
        Debug.LogWarning(Key + "  " + value);
        return value;

    }

    public static void WriteString(string Key, SectionName section = SectionName.config, string defaultValue = "")
    {
        string sectionName = section.ToString();
        Action<INIParser> action =
            (ini) =>
            {
                ini.WriteValue(sectionName, Key, defaultValue);
            };
        OpenAndReadINI(mINIFileName, action);
    }

    public static void WriteBool(string Key, SectionName section = SectionName.config, bool defaultValue = false)
    {
        string sectionName = section.ToString();
        Action<INIParser> action =
            (ini) =>
            {
                ini.WriteValue(sectionName, Key, defaultValue);
            };
        OpenAndReadINI(mINIFileName, action);
    }
    public static void WriteFloat(string Key, SectionName section = SectionName.config, float defaultValue = 0)
    {
        string sectionName = section.ToString();
        Action<INIParser> action =
            (ini) =>
            {
                ini.WriteValue(sectionName, Key, defaultValue);
            };
        OpenAndReadINI(mINIFileName, action);
    }

    public static int GetInt(string Key, SectionName section = SectionName.config, int defaultValue = 0)
    {
        int value = defaultValue;
        string sectionName = section.ToString();

        Action<INIParser> action =
            (ini) =>
            {
                if (!ini.IsKeyExists(sectionName, Key))
                    ini.WriteValue(sectionName, Key, defaultValue);
                value = ini.ReadValue(sectionName, Key, defaultValue);
            };
        OpenAndReadINI(mINIFileName, action);
        Debug.LogWarning(Key + "  " + value);
        return value;
    }

    static void OpenAndReadINI(string path, Action<INIParser> actionRead)
    {
        try
        {
            if (!File.Exists(path))
            {
                File.Create(path).Close();
                Debug.LogWarning("Create Success:" + path);
            }
            //else
            {
                INIParser iniParser = new INIParser();
                iniParser.Open(path);

                actionRead(iniParser);

                iniParser.Close();
            }
        }
        catch (Exception e)
        {
            Debug.LogError("INIFile Not Found Or Create:\r\n" + path + "\r\n" + e);
        }
    }
}
/*******************************
Version: 1.0
Project Boon
*******************************/

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using UnityEngine;

public class INIParser
{
    #region "Declarations"

    // *** Error: In case there're errors, this will changed to some value other than 1 ***
    // Error codes: 
    // 1: Null TextAsset
    public int error = 0;

    // *** Lock for thread-safe access to file and local cache ***
    private object m_Lock = new object();

    // *** File name ***
    private string m_FileName = null;
    public string FileName
    {
        get
        {
            return m_FileName;
        }
    }

    // ** String represent Ini
    private string m_iniString = null;
    public string iniString
    {
        get
        {
            return m_iniString;
        }
    }

    // *** Automatic flushing flag ***
    private bool m_AutoFlush = false;

    // *** Local cache ***
    private Dictionary<string, Dictionary<string, string>> m_Sections = new Dictionary<string, Dictionary<string, string>>();
    private Dictionary<string, Dictionary<string, string>> m_Modified = new Dictionary<string, Dictionary<string, string>>();

    // *** Local cache modified flag ***
    private bool m_CacheModified = false;

    #endregion

    #region "Methods"

    // *** Open ini file by path ***
    public void Open(string path)
    {
        m_FileName = path;

        if (File.Exists(m_FileName))
        {
            m_iniString = File.ReadAllText(m_FileName);
        }
        else
        {
            //If file does not exist, create one
            var temp = File.Create(m_FileName);
            temp.Close();
            m_iniString = "";
        }

        Initialize(m_iniString, false);
    }

    // *** Open ini file by TextAsset: All changes is saved to local storage ***
    public void Open(TextAsset name)
    {
        if (name == null)
        {
            // In case null asset, treat as opened an empty file
            error = 1;
            m_iniString = "";
            m_FileName = null;
            Initialize(m_iniString, false);
        }
        else
        {
            m_FileName = Application.persistentDataPath + name.name;

            //*** Find the TextAsset in the local storage first ***
            if (File.Exists(m_FileName))
            {
                m_iniString = File.ReadAllText(m_FileName);
            }
            else m_iniString = name.text;
            Initialize(m_iniString, false);
        }
    }

    // *** Open ini file from string ***
    public void OpenFromString(string str)
    {
        m_FileName = null;
        Initialize(str, false);
    }

    // *** Get the string content of ini file ***
    public override string ToString()
    {
        return m_iniString;
    }

    private void Initialize(string iniString, bool AutoFlush)
    {
        m_iniString = iniString;
        m_AutoFlush = AutoFlush;
        Refresh();
    }

    // *** Close, save all changes to ini file ***
    public void Close()
    {
        lock (m_Lock)
        {
            PerformFlush();

            //Clean up memory
            m_FileName = null;
            m_iniString = null;
        }
    }

    // *** Parse section name ***
    private string ParseSectionName(string Line)
    {
        if (!Line.StartsWith("[")) return null;
        if (!Line.EndsWith("]")) return null;
        if (Line.Length < 3) return null;
        return Line.Substring(1, Line.Length - 2);
    }

    // *** Parse key+value pair ***
    private bool ParseKeyValuePair(string Line, ref string Key, ref string Value)
    {
        // *** Check for key+value pair ***
        int i;
        if ((i = Line.IndexOf('=')) <= 0) return false;

        int j = Line.Length - i - 1;
        Key = Line.Substring(0, i).Trim();
        if (Key.Length <= 0) return false;

        Value = (j > 0) ? (Line.Substring(i + 1, j).Trim()) : ("");
        return true;
    }

    // *** If a line is neither SectionName nor key+value pair, it's a comment ***
    private bool isComment(string Line)
    {
        string tmpKey = null, tmpValue = null;
        if (ParseSectionName(Line) != null) return false;
        if (ParseKeyValuePair(Line, ref tmpKey, ref tmpValue)) return false;
        return true;
    }

    // *** Read file contents into local cache ***
    private void Refresh()
    {
        lock (m_Lock)
        {
            StringReader sr = null;
            try
            {
                // *** Clear local cache ***
                m_Sections.Clear();
                m_Modified.Clear();

                // *** String Reader ***
                sr = new StringReader(m_iniString);


                // *** Read up the file content ***
                Dictionary<string, string> CurrentSection = null;
                string s;
                string SectionName;
                string Key = null;
                string Value = null;
                while ((s = sr.ReadLine()) != null)
                {
                    s = s.Trim();

                    // *** Check for section names ***
                    SectionName = ParseSectionName(s);
                    if (SectionName != null)
                    {
                        // *** Only first occurrence of a section is loaded ***
                        if (m_Sections.ContainsKey(SectionName))
                        {
                            CurrentSection = null;
                        }
                        else
                        {
                            CurrentSection = new Dictionary<string, string>();
                            m_Sections.Add(SectionName, CurrentSection);
                        }
                    }
                    else if (CurrentSection != null)
                    {
                        // *** Check for key+value pair ***
                        if (ParseKeyValuePair(s, ref Key, ref Value))
                        {
                            // *** Only first occurrence of a key is loaded ***
                            if (!CurrentSection.ContainsKey(Key))
                            {
                                CurrentSection.Add(Key, Value);
                            }
                        }
                    }
                }
            }
            finally
            {
                // *** Cleanup: close file ***
                if (sr != null) sr.Close();
                sr = null;
            }
        }
    }

    private void PerformFlush()
    {
        // *** If local cache was not modified, exit ***
        if (!m_CacheModified) return;
        m_CacheModified = false;

        // *** Copy content of original iniString to temporary string, replace modified values ***
        StringWriter sw = new StringWriter();

        try
        {
            Dictionary<string, string> CurrentSection = null;
            Dictionary<string, string> CurrentSection2 = null;
            StringReader sr = null;
            try
            {
                // *** Open the original file ***
                sr = new StringReader(m_iniString);

                // *** Read the file original content, replace changes with local cache values ***
                string s;
                string SectionName;
                string Key = null;
                string Value = null;
                bool Unmodified;
                bool Reading = true;

                bool Deleted = false;
                string Key2 = null;
                string Value2 = null;

                StringBuilder sb_temp;

                while (Reading)
                {
                    s = sr.ReadLine();
                    Reading = (s != null);

                    // *** Check for end of iniString ***
                    if (Reading)
                    {
                        Unmodified = true;
                        s = s.Trim();
                        SectionName = ParseSectionName(s);
                    }
                    else
                    {
                        Unmodified = false;
                        SectionName = null;
                    }

                    // *** Check for section names ***
                    if ((SectionName != null) || (!Reading))
                    {
                        if (CurrentSection != null)
                        {
                            // *** Write all remaining modified values before leaving a section ****
                            if (CurrentSection.Count > 0)
                            {
                                // *** Optional: All blank lines before new values and sections are removed ****
                                sb_temp = sw.GetStringBuilder();
                                while ((sb_temp[sb_temp.Length - 1] == '\n') || (sb_temp[sb_temp.Length - 1] == '\r'))
                                {
                                    sb_temp.Length = sb_temp.Length - 1;
                                }
                                sw.WriteLine();

                                foreach (string fkey in CurrentSection.Keys)
                                {
                                    if (CurrentSection.TryGetValue(fkey, out Value))
                                    {
                                        sw.Write(fkey);
                                        sw.Write('=');
                                        sw.WriteLine(Value);
                                    }
                                }
                                sw.WriteLine();
                                CurrentSection.Clear();
                            }
                        }

                        if (Reading)
                        {
                            // *** Check if current section is in local modified cache ***
                            if (!m_Modified.TryGetValue(SectionName, out CurrentSection))
                            {
                                CurrentSection = null;
                            }
                        }
                    }
                    else if (CurrentSection != null)
                    {
                        // *** Check for key+value pair ***
                        if (ParseKeyValuePair(s, ref Key, ref Value))
                        {
                            if (CurrentSection.TryGetValue(Key, out Value))
                            {
                                // *** Write modified value to temporary file ***
                                Unmodified = false;
                                CurrentSection.Remove(Key);

                                sw.Write(Key);
                                sw.Write('=');
                                sw.WriteLine(Value);
                            }
                        }
                    }

                    // ** Check if the section/key in current line has been deleted ***
                    if (Unmodified)
                    {
                        if (SectionName != null)
                        {
                            if (!m_Sections.ContainsKey(SectionName))
                            {
                                Deleted = true;
                                CurrentSection2 = null;
                            }
                            else
                            {
                                Deleted = false;
                                m_Sections.TryGetValue(SectionName, out CurrentSection2);
                            }

                        }
                        else if (CurrentSection2 != null)
                        {
                            if (ParseKeyValuePair(s, ref Key2, ref Value2))
                            {
                                if (!CurrentSection2.ContainsKey(Key2)) Deleted = true;
                                else Deleted = false;
                            }
                        }
                    }


                    // *** Write unmodified lines from the original iniString ***
                    if (Unmodified)
                    {
                        if (isComment(s)) sw.WriteLine(s);
                        else if (!Deleted) sw.WriteLine(s);
                    }
                }

                // *** Close string reader ***
                sr.Close();
                sr = null;
            }
            finally
            {
                // *** Cleanup: close string reader ***                  
                if (sr != null) sr.Close();
                sr = null;
            }

            // *** Cycle on all remaining modified values ***
            foreach (KeyValuePair<string, Dictionary<string, string>> SectionPair in m_Modified)
            {
                CurrentSection = SectionPair.Value;
                if (CurrentSection.Count > 0)
                {
                    sw.WriteLine();

                    // *** Write the section name ***
                    sw.Write('[');
                    sw.Write(SectionPair.Key);
                    sw.WriteLine(']');

                    // *** Cycle on all key+value pairs in the section ***
                    foreach (KeyValuePair<string, string> ValuePair in CurrentSection)
                    {
                        // *** Write the key+value pair ***
                        sw.Write(ValuePair.Key);
                        sw.Write('=');
                        sw.WriteLine(ValuePair.Value);
                    }
                    CurrentSection.Clear();
                }
            }
            m_Modified.Clear();

            // *** Get result to iniString ***
            m_iniString = sw.ToString();
            sw.Close();
            sw = null;

            // ** Write iniString to file ***
            if (m_FileName != null)
            {
                File.WriteAllText(m_FileName, m_iniString);
            }
        }
        finally
        {
            // *** Cleanup: close string writer ***                  
            if (sw != null) sw.Close();
            sw = null;
        }
    }

    // *** Check if the section exists ***
    public bool IsSectionExists(string SectionName)
    {
        return m_Sections.ContainsKey(SectionName);
    }

    // *** Check if the key exists ***
    public bool IsKeyExists(string SectionName, string Key)
    {
        Dictionary<string, string> Section;

        // *** Check if the section exists ***
        if (m_Sections.ContainsKey(SectionName))
        {
            m_Sections.TryGetValue(SectionName, out Section);

            // If the key exists
            return Section.ContainsKey(Key);
        }
        else return false;
    }

    // *** Delete a section in local cache ***
    public void SectionDelete(string SectionName)
    {
        // *** Delete section if exists ***
        if (IsSectionExists(SectionName))
        {
            lock (m_Lock)
            {
                m_CacheModified = true;
                m_Sections.Remove(SectionName);

                //Also delete in modified cache if exist
                m_Modified.Remove(SectionName);

                // *** Automatic flushing : immediately write any modification to the file ***
                if (m_AutoFlush) PerformFlush();
            }
        }
    }

    // *** Delete a key in local cache ***
    public void KeyDelete(string SectionName, string Key)
    {
        Dictionary<string, string> Section;

        //Delete key if exists
        if (IsKeyExists(SectionName, Key))
        {
            lock (m_Lock)
            {
                m_CacheModified = true;
                m_Sections.TryGetValue(SectionName, out Section);
                Section.Remove(Key);

                //Also delete in modified cache if exist
                if (m_Modified.TryGetValue(SectionName, out Section)) Section.Remove(SectionName);

                // *** Automatic flushing : immediately write any modification to the file ***
                if (m_AutoFlush) PerformFlush();
            }
        }

    }

    // *** Read a value from local cache ***
    public string ReadValue(string SectionName, string Key, string DefaultValue)
    {
        lock (m_Lock)
        {
            // *** Check if the section exists ***
            Dictionary<string, string> Section;
            if (!m_Sections.TryGetValue(SectionName, out Section)) return DefaultValue;

            // *** Check if the key exists ***
            string Value;
            if (!Section.TryGetValue(Key, out Value)) return DefaultValue;

            // *** Return the found value ***
            return Value;
        }
    }

    // *** Insert or modify a value in local cache ***
    public void WriteValue(string SectionName, string Key, string Value)
    {
        lock (m_Lock)
        {
            // *** Flag local cache modification ***
            m_CacheModified = true;

            // *** Check if the section exists ***
            Dictionary<string, string> Section;
            if (!m_Sections.TryGetValue(SectionName, out Section))
            {
                // *** If it doesn't, add it ***
                Section = new Dictionary<string, string>();
                m_Sections.Add(SectionName, Section);
            }

            // *** Modify the value ***
            if (Section.ContainsKey(Key)) Section.Remove(Key);
            Section.Add(Key, Value);

            // *** Add the modified value to local modified values cache ***
            if (!m_Modified.TryGetValue(SectionName, out Section))
            {
                Section = new Dictionary<string, string>();
                m_Modified.Add(SectionName, Section);
            }

            if (Section.ContainsKey(Key)) Section.Remove(Key);
            Section.Add(Key, Value);

            // *** Automatic flushing : immediately write any modification to the file ***
            if (m_AutoFlush) PerformFlush();
        }
    }

    // *** Encode byte array ***
    private string EncodeByteArray(byte[] Value)
    {
        if (Value == null) return null;

        StringBuilder sb = new StringBuilder();
        foreach (byte b in Value)
        {
            string hex = Convert.ToString(b, 16);
            int l = hex.Length;
            if (l > 2)
            {
                sb.Append(hex.Substring(l - 2, 2));
            }
            else
            {
                if (l < 2) sb.Append("0");
                sb.Append(hex);
            }
        }
        return sb.ToString();
    }

    // *** Decode byte array ***
    private byte[] DecodeByteArray(string Value)
    {
        if (Value == null) return null;

        int l = Value.Length;
        if (l < 2) return new byte[] { };

        l /= 2;
        byte[] Result = new byte[l];
        for (int i = 0; i < l; i++) Result[i] = Convert.ToByte(Value.Substring(i * 2, 2), 16);
        return Result;
    }

    // *** Getters for various types ***
    public bool ReadValue(string SectionName, string Key, bool DefaultValue)
    {
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(System.Globalization.CultureInfo.InvariantCulture));
        int Value;
        if (int.TryParse(StringValue, out Value)) return (Value != 0);
        return DefaultValue;
    }

    public int ReadValue(string SectionName, string Key, int DefaultValue)
    {
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        int Value;
        if (int.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
        return DefaultValue;
    }

    public long ReadValue(string SectionName, string Key, long DefaultValue)
    {
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        long Value;
        if (long.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
        return DefaultValue;
    }

    public double ReadValue(string SectionName, string Key, double DefaultValue)
    {
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        double Value;
        if (double.TryParse(StringValue, NumberStyles.Any, CultureInfo.InvariantCulture, out Value)) return Value;
        return DefaultValue;
    }

    public byte[] ReadValue(string SectionName, string Key, byte[] DefaultValue)
    {
        string StringValue = ReadValue(SectionName, Key, EncodeByteArray(DefaultValue));
        try
        {
            return DecodeByteArray(StringValue);
        }
        catch (FormatException)
        {
            return DefaultValue;
        }
    }

    public DateTime ReadValue(string SectionName, string Key, DateTime DefaultValue)
    {
        string StringValue = ReadValue(SectionName, Key, DefaultValue.ToString(CultureInfo.InvariantCulture));
        DateTime Value;
        if (DateTime.TryParse(StringValue, CultureInfo.InvariantCulture, DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.AssumeLocal, out Value)) return Value;
        return DefaultValue;
    }

    // *** Setters for various types ***
    public void WriteValue(string SectionName, string Key, bool Value)
    {
        WriteValue(SectionName, Key, (Value) ? ("1") : ("0"));
    }

    public void WriteValue(string SectionName, string Key, int Value)
    {
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    public void WriteValue(string SectionName, string Key, long Value)
    {
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    public void WriteValue(string SectionName, string Key, double Value)
    {
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    public void WriteValue(string SectionName, string Key, byte[] Value)
    {
        WriteValue(SectionName, Key, EncodeByteArray(Value));
    }

    public void WriteValue(string SectionName, string Key, DateTime Value)
    {
        WriteValue(SectionName, Key, Value.ToString(CultureInfo.InvariantCulture));
    }

    #endregion
}