//--------------------------日期:2013-8-28
//--------------------------版本:2.0.1.0
//--------------------------作者:itrycn
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ryCommon
{
    /// <summary>
    /// Ini操作类
    /// </summary>
    public class Ini
    {
        // 声明INI文件的写操作函数 WritePrivateProfileString()
　　    [System.Runtime.InteropServices.DllImport("kernel32")]
　　    private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
     /// <summary>
     /// 写入Ini
     /// </summary>
     /// <param name="section"></param>
     /// <param name="key"></param>
     /// <param name="val"></param>
     /// <param name="filePath"></param>
     /// <returns></returns>
        [DllImport("kernel32")]
        public static extern bool WritePrivateProfileString(byte[] section, byte[] key, byte[] val, string filePath);
        /// <summary>
        /// 获取Ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="def"></param>
        /// <param name="retVal"></param>
        /// <param name="size"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [DllImport("kernel32")]
        public static extern int GetPrivateProfileString(byte[] section, byte[] key, byte[] def, byte[] retVal, int size, string filePath);

        /// <summary>
        /// 声明INI文件的读操作函数 GetPrivateProfileString()
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="def"></param>
        /// <param name="retVal"></param>
        /// <param name="size"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [System.Runtime.InteropServices.DllImport("kernel32")]
　　    private static extern int GetPrivateProfileString(string section, string key, string def, System.Text.StringBuilder retVal, int size, string filePath);
        /// <summary>
        /// 声明INI文件的读操作函数 GetPrivateProfileString()
        /// </summary>
        /// <param name="lpAppName"></param>
        /// <param name="lpReturnedString"></param>
        /// <param name="nSize"></param>
        /// <param name="lpFileName"></param>
        /// <returns></returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private static extern uint GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName);
        /// <summary>
        /// 声明INI文件的读操作函数 GetPrivateProfileString()
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="defVal"></param>
        /// <param name="retVal"></param>
        /// <param name="size"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        [DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);
        /// <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);
        private readonly string sPath = null;
        /// <summary>
        /// 编码
        /// </summary>
        public Encoding Encoding { get; set; } = Encoding.Default;
        /// <summary>
        /// Ini操作类
        /// </summary>
        /// <param name="path"></param>
        public Ini(string path)
　　    {
　　       this.sPath = path;
            if(path!="" && !System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(path)))
            {
                System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
            }
　　    }
        /// <summary>  
        /// 根据section取所有key和值
        /// </summary>  
        /// <param name="section"></param>  
        /// <returns></returns>  
        public string[] GetAllKeysAndValue(string section)
        {
            UInt32 MAX_BUFFER = 32767;
            string[] items = new string[0];
            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));
            UInt32 bytesReturned = GetPrivateProfileSection(section, pReturnedString, MAX_BUFFER, sPath);
            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文件中指定INI文件中的所有节点名称(Section)  
        /// </summary>  
        /// <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, sPath);
            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文件
        /// </summary>
        /// <param name="section">段，格式[]</param>
        /// <param name="key">键</param>
        /// <returns>返回byte类型的section组或键值组</returns>
        public byte[] IniReadValues(string section, string key)
        {
            int size = 1000;
            byte[] buffer = new byte[size];
            int count = GetPrivateProfileString(GetBytes(section), GetBytes(key), GetBytes(""), buffer, size, sPath);
            return buffer;
        }
        /// <summary>
        /// 根据section取所有key
        /// </summary>
        /// <param name="section"></param>
        /// <returns></returns>
        public string[] GetKey(string section)
        {
            byte[] allSection = IniReadValues(section, null);
            //编码所有key的string类型
            string sections = Encoding.GetString(allSection).TrimEnd('\0');
            //获取key的数组
            return sections.Split(new char[1] { '\0' });
        }
        //与ini交互必须统一编码格式
        private byte[] GetBytes(string s)
        {
            return null == s ? null :Encoding.GetBytes(s);
        }
        /// <summary>
        /// 写入ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void WriteIni(string section, string key, string value)
        {
            WritePrivateProfileString(GetBytes(section), GetBytes(key), GetBytes(value), sPath);
        }
        
        /// <summary>
        /// 写入ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void WriteIni(string section, string key, int value)
        {
            WriteIni(section, key, value.ToString());
        }
        /// <summary>
        /// 写入ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void WriteIni(string section, string key, Int64 value)
        {
            WriteIni(section, key, value.ToString());
        }
        /// <summary>
        /// 写入ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void WriteIni(string section, string key, decimal value)
        {
            WriteIni(section, key, value.ToString());
        }
        /// <summary>
        /// 写入ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void WriteIni(string section, string key, double value)
        {
            WriteIni(section, key, value.ToString());
        }
        /// <summary>
        /// 写入Ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void WriteIni(string section, string key, bool value)
        {
          if (value)
          {
                WriteIni(section, key, "1");
          }
          else
          {
                WriteIni(section, key, "0");
          }
       }
       /// <summary>
       /// 读取Ini
       /// </summary>
       /// <param name="section"></param>
       /// <param name="key"></param>
       /// <returns></returns>
       public string ReadIni(string section, string key)
       {
            return ReadIni(section, key,"") ;
       }
        /// <summary>
        /// 读取Ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
       public string ReadIni(string section, string key,string defValue)
       {
            int size = 255;
            byte[] buffer = new byte[size];
            int count = GetPrivateProfileString(GetBytes(section), GetBytes(key), GetBytes(defValue), buffer, size, sPath);
            return Encoding.GetString(buffer, 0, count).Trim();
       }
        /// <summary>
        /// 读取Ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
      public int ReadIni(string section, string key, int defValue)
      {
          try
          {
              return Convert.ToInt32(ReadIni(section, key, defValue.ToString()));
          }
          catch
          {
              return defValue;
          }
      }
        /// <summary>
        /// 读取Ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public int ReadIni(string section, string key, int min, int max, int defValue)
        {
            try
            {
                int resultI = ReadIni(section, key, defValue);
                if (resultI >= min && resultI <= max)
                {
                    return resultI;
                }
                else
                {
                    return defValue;
                }
            }
            catch
            {
                return defValue;
            }
        }
        /// <summary>
        /// 写入ini
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        public bool ReadIni(string section, string key, bool defValue)
      {
          try
          {
             string tmpStr= ReadIni(section, key, defValue.ToString());
             if (tmpStr.ToLower() == "true" || tmpStr=="1")
             {
                 return true;
             }
             else if (tmpStr.ToLower() == "false" || tmpStr == "0" || tmpStr == "-1")
             {
                 return false;
             }
             else
             {
                 return defValue;
             }
          }
          catch
          {
              return defValue;
          }
      }
        /// <summary>
        /// 删除Ini的Key
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
      public void DelKey(string section, string key)
      {
            WritePrivateProfileString(GetBytes(section), GetBytes(key), null, sPath);
      }
       /// <summary>
       /// 删除Ini节点
       /// </summary>
       /// <param name="section"></param>
      public void DelSection(string section)
      {
            WritePrivateProfileString(GetBytes(section),null, null, sPath);
      } 
    }
}
