C#完整的ini实现类

 完整的ini类

https://files.cnblogs.com/files/xe2011/IniFiles_2021-9-22-21_52_48.rar

 

f1

 

使用

 

引用

using IniFiles;

 

实例化

 

IniFile ini = new IniFile(" c:\app.ini");

 

yourInipath 可以是如下2种方法

和EXE在同一目录的路径: app.ini

完整的文件路径: c:\app.ini

 

读取内容

ini文件结构

[user]
name = "测试"
age = "14"
phone = "12345678910"
sex = "true"
 

[note]
Count= "3"
0= "【推荐】了解你才能更懂你,博客园首发问卷调查,助力社区新升级"
1= "【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库"
2= "【推荐】独家首发 | 900页阿里文娱技术实战,8大技术栈解析技术全景"

 

读取数据

string s =  ini.ReadString("user","name"); //返回 测试

int age = ini.ReadString("user","age"); //14

bool b = ini.ReadBoolean("user","sex"); //读出来的值总是 小写的  true或false

 

读取多行内容

textBox1.Lines =  ini.ReadStringArrayText("note");

 

列出ini文件中所有的字段名

string[] sections = ini.SectionNames;

 

读取[user]字段下的所有键名

string[] keys= ini.ReadKeyNames("user");

 

读取[user]字段下的所有键名的值

string[] values= ini.ReadSectionKeyValues("user");

 

 

写入数据

  ini.WriteString("user","name",”test”);

  ini.WriteInteger("user","age",18); 

  ini.WriteBoolean("user","sex",true); 

 

可以将多行文本保存到INI中

  ini.WriteStringArray("note",textBox1.Lines);

 

读取异常

     如果.ini文件不存在、或者目标字段、或者目标键值不存在则抛出异常。

 

静态读写

使用 IniFile.Instance.方法名

如果使用此种写法则 配置文件默认和exe在同一目录,假如程序为 app1.exe则配置文件为app1.exe.ini

 

   textBox1.Text = IniFile.Instance.ReadString("conf","name");

   IniFile.Instance.WriteString("conf","name",textBox1.Text);

 

 

 

IniFile.cs

/* ----------------------------------------------------------
 *
 * 作者:qq450640526
 *
 * 微信:roman_2015
 *
 * 2020年7月13日, PM 08:40:56
 * 完整支持
 * Ansi、GB2312、UTF-8
 * 2020年7月12日, AM 11:34:58
 * 编码格式必须是gb2312的否则中文读不出来。
 * 折中办法让代码只读取 GB2312的编码格式文件
 * 文件编码为gb2312则可以使用中文字段
 * 字符的名称不区分大小写
 *
 * 2020年7月15日, AM 10:04:14
 * 路径支持这种短写方法
 * "TEST.INI"了
 *  Application.StartupPath + "\\data\\TEST.INI"  ;
 *
 *
 * 博客:https://www.cnblogs.com/xe2011/
 * 参考:https://www.jb51.net/article/46773.htm
 *
 * 版本历史:
 *
 *      V1.0    2020年7月11日, PM 09:49:40
 *              实现基础操作
------------------------------------------------------------ */

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;


namespace IniFiles {

   public class IniFile {

        /// <summary>
        /// 在exe相对路径中自动产生 一个 配置文件
        ///程序为 app1.exe 对应的配置 app1.exe.ini
        ///
        ///   可以这样直接使用
        ///     IniFile.Instance.WriteString("conf","name",textBox1.Text);
        ///     textBox1.Text = IniFile.Instance.ReadString("conf","name");
        /// </summary>
        public static IniFile Instance {
            get {

                //在dll中获得调用当前DLL的路径
                //在DLL中用不了这样的写法 Application.ExecutablePath + ".ini";
                string path = Assembly.GetEntryAssembly().Location + ".ini";////app1.exe 对应的 app1.exe.ini
                return new IniFile(path);
            }
        }

        /// <param name="iniFileName">ini的路径 使用相对路径"test.ini"或者完整路径"X:\test.ini"</param>
        public IniFile(string iniFileName) {
            _iniFileName = Path.GetFullPath(iniFileName);
            if (File.Exists(_iniFileName)) {
                encoding = _FileEncoding;
            }
        }

        public Encoding _FileEncoding {
            get {
                return FileEncoding.GetEncoding(_iniFileName);
            }
        }

        #region 核心部分

        private static byte[] GetBytes(string s) {
            return null == s ? null : Encoding.GetEncoding("utf-8").GetBytes(s);
        }

        //读取utf8编码格式的文件内容
        private string GetStringUTF8(string section,string key,string sValue,string inifile) {
            int size = 65535;
            byte[] buffer = new byte[size];
            int count = GetPrivateProfileString(GetBytes(section),GetBytes(key),GetBytes(sValue),buffer,size,inifile);
            return Encoding.GetEncoding("utf-8").GetString(buffer,0,count);
        }
        //写入utf8编码格式的文件内容
        private bool WriteStringUTF8(string section,string key,string sValue,string fileName,string encodingName = "utf-8") {
            return WritePrivateProfileString(GetBytes(section),GetBytes(key),GetBytes(sValue),fileName);
        }

        //读取信息
        private string Read(string section,string key,string sValue = "") {
            TestExecption(section,key);
            if (encoding != Encoding.UTF8) {
                //ansi或gb2312格式的编码
                StringBuilder sb = new StringBuilder(4096);
                GetPrivateProfileString(section,key,sValue,sb,4096,_iniFileName);
                return sb.ToString();
            } else {
                return GetStringUTF8(section,key,sValue,_iniFileName);
            }
        }

        //写入信息
        private bool Write(string section,string key,string sValue) {
            if (encoding != Encoding.UTF8) {//ansi或gb2312格式的编码
                return WritePrivateProfileString(section,key," \"" + sValue + "\"",_iniFileName);
            } else {
                return WriteStringUTF8(section,key," \"" + sValue + "\"",_iniFileName);
            }
        }
        #endregion

        #region 字段、判断、测试异常

        //判断字段是否存在,字段和键名不区分大小写
        public bool IsSectionExists(string section) {
            //全部转换成小写来判断 不区分大小写了
            string[] arr = SectionNames;

            for (int i = 0; i < arr.Length; i++) {
                arr[i] = arr[i].ToLower();
            }
            section = section.ToLower();

            return Array.IndexOf(arr,section) > -1;
        }

        //检查某个section下的某个键值是否存在,字段和键名不区分大小写
        public bool IsKeyExists(string section,string key) {
            string[] arr = ReadKeyNames(section);

            for (int i = 0; i < arr.Length; i++) {
                arr[i] = arr[i].ToLower();
            }

            key = key.ToLower();
            return Array.IndexOf(arr,key) > -1;
        }

        //字段或者键名不存在,尝试读取时抛出异常
        private void TestExecption(string section,string key) {
            if (!File.Exists(_iniFileName))
                throw new ApplicationException("文件不存在! 读取数据失败!\n\"" + _iniFileName + "\"");
            else if (!IsSectionExists(section)) {

                throw new ApplicationException("字段[" + section + "]不存在!\n路径: \"" + _iniFileName + "\"");

            } else if (!IsKeyExists(section,key.ToLower())) {

                throw new ApplicationException("文件“" + _iniFileName + "”的\n字段[" + section + "]的“" + key + "”键名,不存在!");

            }
        }

        //列出INI文件中所有的字段名
        public string[] SectionNames {
            get {
                List<string> result = new List<string>();

                byte[] buf = new byte[65536];
                uint len = GetPrivateProfileStringA(null,null,null,buf,buf.Length,_iniFileName);
                int j = 0;
                for (int i = 0; i < len; i++) {
                    if (buf[i] == 0) {
                        result.Add(Encoding.Default.GetString(buf,j,i - j));
                        j = i + 1;
                    }
                }
                return result.ToArray();
            }
        }

        //读取字段下的所有键名
        public string[] ReadKeyNames(string section) {
            List<string> list = new List<string>();
            byte[] buf = new byte[65536];
            uint len = GetPrivateProfileStringA(section,null,null,buf,buf.Length,_iniFileName);
            int j = 0;
            for (int i = 0; i < len; i++) {
                if (buf[i] == 0) {
                    list.Add(Encoding.Default.GetString(buf,j,i - j));
                    j = i + 1;
                }
            }
            return list.ToArray();
        }

        //读取字段值的所有的键的值
        public string[] ReadSectionKeyValues(string section) {
            List<string> result = new List<string>();
            foreach (string key in ReadKeyNames(section)) {
                string s = Read(section,key);
                result.Add(s);
            }
            return result.ToArray();
        }

        //清除某个section 及其字段下所有的所有内容 
        public bool DeleteSection(string section) {
            bool b = WritePrivateProfileString(section,null,null,_iniFileName);
            if (!b) {
                throw (new ApplicationException("无法清除Ini文件中的section"));
            }
            return b;
        }

        //删除某个section下的键 及其对应的值
        public bool DeleteKey(string section,string key) {
            return WritePrivateProfileString(section,key,null,_iniFileName);
        }
        #endregion

        #region 读和写 string、Boolean、Integer、Single、Double、StringArray
        public string ReadString(string section,string key,string sValue = "") {
            return Read(section,key,sValue);
        }

        public bool WriteString(string section,string key,string sValue) {
            return Write(section,key,sValue);
        }

        //返回值为true false 不区分大小写
        public bool ReadBoolean(string section,string key,bool sValue = false) {
            string v = sValue.ToString().ToLower();
            string s = Read(section,key,v).ToLower().Trim();

            //必须要返回一个值
            return Convert.ToBoolean(s);
        }

        public bool WriteBoolean(string section,string key,bool sValue) {
            return Write(section,key,sValue.ToString().Trim().ToLower());
        }

        public int ReadInteger(string section,string key,int sValue = 0) {
            string v = sValue.ToString().ToLower();
            string s = Read(section,key,v).Trim();
            return Convert.ToInt32(s);
        }

        public bool WriteInteger(string section,string key,int sValue) {
            return Write(section,key,sValue.ToString().Trim().ToLower());
        }

        public double ReadDouble(string section,string key,double sValue = 0d) {
            string v = sValue.ToString().ToLower();
            string s = Read(section,key,v).ToLower().Trim();
            return Convert.ToDouble(s);
        }

        public bool WriteDouble(string section,string key,double sValue) {
            return Write(section,key,sValue.ToString().Trim().ToLower());
        }

        public double ReadSingle(string section,string key,double sValue = 0d) {
            string v = sValue.ToString().ToLower();
            string s = Read(section,key,v).ToLower().Trim();
            return Convert.ToSingle(s);
        }

        public bool WriteSingle(string section,string key,double sValue) {
            return WriteDouble(section,key,sValue);
        }

        //2014年6月24日19:39:25
        public string[] ReadStringArray(string section) {
            int len = ReadInteger(section,"Count",0);
            List<string> list = new List<string>();
            for (int i = 0; i < len; i++) {
                string s = ReadString(section,i.ToString(),"0");
                list.Add(s);
            }
            return list.ToArray();
        }

        public string ReadStringArrayText(string section) {
            return string.Join("\n",ReadStringArray(section));
        }


        /*  为了确保能正确显示空格请使用单引号 或者双引号将值加入进去
            磁的时候不用解析直接读出来的
            [TEST]
            a = '  asd a as  '
            b = ' a a '
        */
        public void WriteStringArray(string section,string[] stringArray) {
            DeleteSection(section);
            WriteInteger(section,"Count",stringArray.Length);
            for (int i = 0; i < stringArray.Length; i++) {
                //WriteString(section,i.ToString(),"'" + stringArray[i] + "'");
                WriteString(section,i.ToString(),stringArray[i]);
            }
        }

        #endregion

        #region API函数声明 WritePrivateProfileString、 GetPrivateProfileString 、GetPrivateProfileStringA

        [DllImport("kernel32")]
        public static extern bool WritePrivateProfileString(byte[] section,byte[] key,byte[] val,string filePath);

        [DllImport("kernel32")]
        public static extern int GetPrivateProfileString(byte[] section,byte[] key,byte[] def,byte[] retVal,int size,string filePath);


        [DllImport("kernel32")]
        private static extern bool WritePrivateProfileString(string section,string key,string val,string filePath);

        //需要调用GetPrivateProfileString的重载
        [DllImport("kernel32")]
        private static extern long GetPrivateProfileString(string section,string key,string def,StringBuilder retVal,int size,string filePath);

        [DllImport("kernel32")]
        private static extern uint GetPrivateProfileStringA(string section,string key,string def,Byte[] retVal,int size,string filePath);


        #endregion

        #region 变量声明

        Encoding encoding = Encoding.Default;
        string _iniFileName = "";

        #endregion

    }

}

 

FileEncoding.cs

 class FileEncoding {
        /// <summary> 
        /// 给定文件的路径,读取文件的二进制数据,判断文件的编码类型 
        /// </summary> 
        /// <param name="path">文件路径</param> 
        /// <returns>文件的编码类型</returns> 
        public static Encoding GetEncoding(string path) {
            if (File.Exists(path)) {
                FileStream fs = new FileStream(path,FileMode.Open,FileAccess.Read);
                Encoding r = GetType(fs);
                fs.Close();
                return r;
            } else
                return null;
        }

        /// <summary> 
        /// 通过给定的文件流,判断文件的编码类型 
        /// </summary> 
        /// <param name="fs">文件流</param> 
        /// <returns>文件的编码类型</returns> 
        private static Encoding GetType(FileStream fs) {
            byte[] Unicode = new byte[] { 0xFF,0xFE,0x41 };
            byte[] UnicodeBIG = new byte[] { 0xFE,0xFF,0x00 };
            byte[] UTF8 = new byte[] { 0xEF,0xBB,0xBF }; //带BOM 
            Encoding reVal = Encoding.Default;

            BinaryReader r = new BinaryReader(fs,System.Text.Encoding.Default);
            int i;
            int.TryParse(fs.Length.ToString(),out i);
            byte[] ss = r.ReadBytes(i);
            if (IsUTF8Bytes(ss) || (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF)) {
                reVal = Encoding.UTF8;
            } else if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00) {
                reVal = Encoding.BigEndianUnicode;
            } else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41) {
                reVal = Encoding.Unicode;
            }
            r.Close();
            return reVal;

        }

        /// <summary> 
        /// 判断是否是不带 BOM 的 UTF8 格式 
        /// </summary> 
        /// <param name="data"></param> 
        /// <returns></returns> 
        private static bool IsUTF8Bytes(byte[] data) {
            int charByteCounter = 1;
            //计算当前正分析的字符应还有的字节数 
            byte curByte; //当前分析的字节. 
            for (int i = 0; i < data.Length; i++) {
                curByte = data[i];
                if (charByteCounter == 1) {
                    if (curByte >= 0x80) {
                        //判断当前 
                        while (((curByte <<= 1) & 0x80) != 0) {
                            charByteCounter++;
                        }
                        //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X  
                        if (charByteCounter == 1 || charByteCounter > 6) {
                            return false;
                        }
                    }
                } else {
                    //若是UTF-8 此时第一位必须为1 
                    if ((curByte & 0xC0) != 0x80) {
                        return false;
                    }
                    charByteCounter--;
                }
            }
            if (charByteCounter > 1) {
                throw new Exception("非预期的byte格式");
            }
            return true;
        }
    }

 

文件下载

https://download.csdn.net/download/u012663700/12619730

更新内容

 

2020年7月15日, AM 10:04:14
     路径支持这种短写方法
     "TEST.INI"了
      Application.StartupPath + "\\data\\TEST.INI"  ;

 

2020年7月13日, PM 08:40:56
    可以完整读取以下文件编码的内容:Ansi、GB2312、UTF-8
    字段或键名 不区分大小写、并且可以为中文
posted @ 2020-07-15 16:00  XE2011  阅读(841)  评论(0编辑  收藏  举报