• C#完整的ini实现类



    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:	est.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("文件不存在! 读取数据失败!
    "" + _iniFileName + """);
                else if (!IsSectionExists(section)) {
    
                    throw new ApplicationException("字段[" + section + "]不存在!
    路径: "" + _iniFileName + """);
    
                } else if (!IsKeyExists(section,key.ToLower())) {
    
                    throw new ApplicationException("文件“" + _iniFileName + "”的
    字段[" + 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("
    ",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
        字段或键名 不区分大小写、并且可以为中文
  • 相关阅读:
    中介者模式
    观察者模式
    javascript深入理解js闭包
    外观模式
    模板方法模式
    浅析C#深拷贝与浅拷贝
    C#浅拷贝与深拷贝区别
    6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱
    原型模式
    设计模式总结
  • 原文地址:https://www.cnblogs.com/xe2011/p/13306034.html
Copyright © 2020-2023  润新知