使用
引用
using IniFiles;
实例化
IniFile ini = new IniFile(" c:app.ini");
yourInipath 可以是如下2种方法
和EXE在同一目录的路径: app.ini
完整的文件路径: c:app.ini
读取内容
ini文件结构
[user] [note] |
读取数据
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
字段或键名 不区分大小写、并且可以为中文