C# 操做ini文件的類

using System;
using System.Text;
using System.Runtime.InteropServices;namespace File.ini
{
    public class INIFile
    {
        #region INI文件操做

        /*
        * 針對INI文件的API操做方法,其中的節點(Section)、鍵(KEY)都不區分大小寫
        * 若是指定的INI文件不存在,會自動建立該文件。
        * 
        * CharSet定義的時候使用了什麼類型,在使用相關方法時必需要使用相應的類型
        *      例如 GetPrivateProfileSectionNames聲明爲CharSet.Auto,那麼就應該使用 Marshal.PtrToStringAuto來讀取相關內容
        *      若是使用的是CharSet.Ansi,就應該使用Marshal.PtrToStringAnsi來讀取內容
        *      
        */

        #region API聲明

        /// <summary>
        /// 獲取全部節點名稱(Section)
        /// </summary>
        /// <param name="lpszReturnBuffer">存放節點名稱的內存地址,每一個節點之間用\0分隔</param>
        /// <param name="nSize">內存大小(characters)</param>
        /// <param name="lpFileName">Ini文件</param>
        /// <returns>內容的實際長度,爲0表示沒有內容,爲nSize-2表示內存大小不夠</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, uint nSize, string lpFileName);

        /// <summary>
        /// 獲取某個指定節點(Section)中全部KEY和Value
        /// </summary>
        /// <param name="lpAppName">節點名稱</param>
        /// <param name="lpReturnedString">返回值的內存地址,每一個之間用\0分隔</param>
        /// <param name="nSize">內存大小(characters)</param>
        /// <param name="lpFileName">Ini文件</param>
        /// <returns>內容的實際長度,爲0表示沒有內容,爲nSize-2表示內存大小不夠</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName);

        /// <summary>
        /// 讀取INI文件中指定的Key的值
        /// </summary>
        /// <param name="lpAppName">節點名稱。若是爲null,則讀取INI中全部節點名稱,每一個節點名稱之間用\0分隔</param>
        /// <param name="lpKeyName">Key名稱。若是爲null,則讀取INI中指定節點中的全部KEY,每一個KEY之間用\0分隔</param>
        /// <param name="lpDefault">讀取失敗時的默認值</param>
        /// <param name="lpReturnedString">讀取的內容緩衝區,讀取以後,多餘的地方使用\0填充</param>
        /// <param name="nSize">內容緩衝區的長度</param>
        /// <param name="lpFileName">INI文件名</param>
        /// <returns>實際讀取到的長度</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, [In, Out] char[] lpReturnedString, uint nSize, string lpFileName);

        //另外一種聲明方式,使用 StringBuilder 做爲緩衝區類型的缺點是不能接受\0字符,會將\0及其後的字符截斷,
        //因此對於lpAppName或lpKeyName爲null的狀況就不適用
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);

        //再一種聲明,使用string做爲緩衝區的類型同char[]
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, string lpReturnedString, uint nSize, string lpFileName);

        /// <summary>
        /// 將指定的鍵值對寫到指定的節點,若是已經存在則替換。
        /// </summary>
        /// <param name="lpAppName">節點,若是不存在此節點,則建立此節點</param>
        /// <param name="lpString">Item鍵值對,多個用\0分隔,形如key1=value1\0key2=value2
        /// <para>若是爲string.Empty,則刪除指定節點下的全部內容,保留節點</para>
        /// <para>若是爲null,則刪除指定節點下的全部內容,而且刪除該節點</para>
        /// </param>
        /// <param name="lpFileName">INI文件</param>
        /// <returns>是否成功寫入</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]     //能夠沒有此行
        private static extern bool WritePrivateProfileSection(string lpAppName, string lpString, string lpFileName);

        /// <summary>
        /// 將指定的鍵和值寫到指定的節點,若是已經存在則替換
        /// </summary>
        /// <param name="lpAppName">節點名稱</param>
        /// <param name="lpKeyName">鍵名稱。若是爲null,則刪除指定的節點及其全部的項目</param>
        /// <param name="lpString">值內容。若是爲null,則刪除指定節點中指定的鍵。</param>
        /// <param name="lpFileName">INI文件</param>
        /// <returns>操做是否成功</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

        #endregion


        #region 封裝

        protected string iniFile;

        public INIFile(string iniFilePath)
        {
            iniFile = iniFilePath;
        }

        /// <summary>
        /// 讀取INI文件中指定INI文件中的全部節點名稱(Section)
        /// </summary>
        /// <param name="iniFile">Ini文件</param>
        /// <returns>全部節點,沒有內容返回string[0]</returns>
        public string[] GetAllSectionNames()
        {
            uint MAX_BUFFER = 32767;    //默認爲32767

            string[] sections = new string[0];      //返回值

            //申請內存
            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
            uint bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, iniFile);
            if (bytesReturned != 0)
            {
                //讀取指定內存的內容
                string local = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned).ToString();

                //每一個節點之間用\0分隔,末尾有一個\0
                sections = local.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }

            //釋放內存
            Marshal.FreeCoTaskMem(pReturnedString);

            return sections;
        }

        /// <summary>
        /// 獲取INI文件中指定節點(Section)中的全部條目(key=value形式)
        /// </summary>
        /// <param name="iniFile">Ini文件</param>
        /// <param name="section">節點名稱</param>
        /// <returns>指定節點中的全部項目,沒有內容返回string[0]</returns>
        public string[] GetAllItems(string section)
        {
            //返回值形式爲 key=value,例如 Color=Red
            uint MAX_BUFFER = 32767;    //默認爲32767

            string[] items = new string[0];      //返回值

            //分配內存
            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));

            uint bytesReturned = GetPrivateProfileSection(section, pReturnedString, MAX_BUFFER, iniFile);

            if (!(bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))
            {

                string returnedString = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned);
                items = returnedString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }

            Marshal.FreeCoTaskMem(pReturnedString);     //釋放內存

            return items;
        }

        /// <summary>
        /// 獲取INI文件中指定節點(Section)中的全部條目的Key列表
        /// </summary>
        /// <param name="iniFile">Ini文件</param>
        /// <param name="section">節點名稱</param>
        /// <returns>若是沒有內容,反回string[0]</returns>
        public string[] GetAllItemKeys(string section)
        {
            string[] value = new string[0];
            const int SIZE = 1024 * 10;

            if (string.IsNullOrEmpty(section))
            {
                throw new ArgumentException("必須指定節點名稱", "section");
            }

            char[] chars = new char[SIZE];
            uint bytesReturned = GetPrivateProfileString(section, null, null, chars, SIZE, iniFile);

            if (bytesReturned != 0)
            {
                value = new string(chars).Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
            }
            chars = null;

            return value;
        }

        /// <summary>
        /// 讀取INI文件中指定KEY的字符串型值
        /// </summary>
        /// <param name="iniFile">Ini文件</param>
        /// <param name="section">節點名稱</param>
        /// <param name="key">鍵名稱</param>
        /// <param name="defaultValue">若是沒此KEY所使用的默認值</param>
        /// <returns>讀取到的值</returns>
        public string GetStringValue(string section, string key, string defaultValue)
        {
            string value = defaultValue;
            const int SIZE = 1024 * 10;

            if (string.IsNullOrEmpty(section))
            {
                throw new ArgumentException("必須指定節點名稱", "section");
            }

            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("必須指定鍵名稱(key)", "key");
            }

            StringBuilder sb = new StringBuilder(SIZE);
            uint bytesReturned = GetPrivateProfileString(section, key, defaultValue, sb, SIZE, iniFile);

            if (bytesReturned != 0)
            {
                value = sb.ToString();
            }
            sb = null;

            return value;
        }

        /// <summary>
        /// 在INI文件中,將指定的鍵值對寫到指定的節點,若是已經存在則替換
        /// </summary>
        /// <param name="iniFile">INI文件</param>
        /// <param name="section">節點,若是不存在此節點,則建立此節點</param>
        /// <param name="items">鍵值對,多個用\0分隔,形如key1=value1\0key2=value2</param>
        /// <returns></returns>
        public bool WriteItems(string section, string items)
        {
            if (string.IsNullOrEmpty(section))
            {
                throw new ArgumentException("必須指定節點名稱", "section");
            }

            if (string.IsNullOrEmpty(items))
            {
                throw new ArgumentException("必須指定鍵值對", "items");
            }

            return WritePrivateProfileSection(section, items, iniFile);
        }

        /// <summary>
        /// 在INI文件中,指定節點寫入指定的鍵及值。若是已經存在,則替換。若是沒有則建立。
        /// </summary>
        /// <param name="iniFile">INI文件</param>
        /// <param name="section">節點</param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns>操做是否成功</returns>
        public bool WriteValue(string section, string key, string value)
        {
            if (string.IsNullOrEmpty(section))
            {
                throw new ArgumentException("必須指定節點名稱", "section");
            }

            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("必須指定鍵名稱", "key");
            }

            if (value == null)
            {
                throw new ArgumentException("值不能爲null", "value");
            }

            return WritePrivateProfileString(section, key, value, iniFile);

        }

        /// <summary>
        /// 在INI文件中,刪除指定節點中的指定的鍵。
        /// </summary>
        /// <param name="iniFile">INI文件</param>
        /// <param name="section">節點</param>
        /// <param name="key"></param>
        /// <returns>操做是否成功</returns>
        public bool DeleteKey(string section, string key)
        {
            if (string.IsNullOrEmpty(section))
            {
                throw new ArgumentException("必須指定節點名稱", "section");
            }

            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("必須指定鍵名稱", "key");
            }

            return WritePrivateProfileString(section, key, null, iniFile);
        }

        /// <summary>
        /// 在INI文件中,刪除指定的節點。
        /// </summary>
        /// <param name="iniFile">INI文件</param>
        /// <param name="section">節點</param>
        /// <returns>操做是否成功</returns>
        public bool DeleteSection(string section)
        {
            if (string.IsNullOrEmpty(section))
            {
                throw new ArgumentException("必須指定節點名稱", "section");
            }

            return WritePrivateProfileString(section, null, null, iniFile);
        }

        /// <summary>
        /// 在INI文件中,刪除指定節點中的全部內容。
        /// </summary>
        /// <param name="iniFile">INI文件</param>
        /// <param name="section">節點</param>
        /// <returns>操做是否成功</returns>
        public bool EmptySection(string section)
        {
            if (string.IsNullOrEmpty(section))
            {
                throw new ArgumentException("必須指定節點名稱", "section");
            }

            return WritePrivateProfileSection(section, string.Empty, iniFile);
        }

        #endregion

        #endregion

    }
}
相關文章
相關標籤/搜索