C# 读写ini文件
开发工具 VS2010
创建ver.ini配置文件,与应用程序放在同一目录
文件格式
[authorName] author=weisico.com [version] ver=20160903
Windows系统自带的Win32的API函数GetPrivateProfileString()和WritePrivateProfileString()分别实现了对INI文件的读写操作,他们位于kernel32.dll下
C#所使用的.NET框架下的公共类库没有提供直接操作INI文件的类,所以这里调用API函数。 .Net框架下的类库是基于托管代码的,而API函数是基于非托管代码的,(在运行库的控制下执行的代码称作托管代码。相反,在运行库之外运 行的代码称作非托管代码。)如何实现托管代码与非托管代码之间的操作呢?.Net框架的System.Runtime.InteropServices命 名空间下提供各种各样支持COM interop及平台调用服务的成员,其中最重要的属性之一DllImportAttribute可以用来定义用于访问非托管API的平台调用方法,它提 供了对从非托管DLL导出的函数进行调用所必需的信息。
读操作
[DllImport("kernel32")] private static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath); section:要读取的段落名 key: 要读取的键 defVal: 读取异常的情况下的缺省值 retVal: key所对应的值,如果该key不存在则返回空值 size: 值允许的大小 filePath: INI文件的完整路径和文件名
写操作
[DllImport("kernel32")] private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); section: 要写入的段落名 key: 要写入的键,如果该key存在则覆盖写入 val: key所对应的值 filePath: INI文件的完整路径和文件名
完整代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using Microsoft.Win32; using System.IO; using System.Runtime.InteropServices; namespace RwIni { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { textBox1.Text = GetPrivateProfileString("version", "ver"); } private void button2_Click(object sender, EventArgs e) { string iniValue = textBox1.Text; if (iniValue != "") { WritePrivateProfileString("version", "ver", iniValue); if (WritePrivateProfileString("version", "ver", iniValue) != 0) { MessageBox.Show("写入成功", "消息提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } else { MessageBox.Show("请输入版本号", "消息提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } } /// <summary> /// 软件安装路径,以此exe所在的路径为准。 /// </summary> string installDirectory = null; private string InstallDirectory { get { if (string.IsNullOrEmpty(installDirectory)) { string sPath = System.Reflection.Assembly.GetExecutingAssembly().Location; installDirectory = Path.GetDirectoryName(sPath) + @"\"; } return installDirectory; } } private string startUpIniFileName = null; public string StartUpIniFileName { get { if (string.IsNullOrEmpty(startUpIniFileName)) { startUpIniFileName = InstallDirectory + "ver.ini"; } return startUpIniFileName; } } [DllImport("kernel32")] private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath); [DllImport("kernel32")] private static extern long WritePrivateProfileString(string section, string key, string value, string filePath); /// <summary> /// 从Ini文件获取数据 /// </summary> /// <param name="section">应用程序</param> /// <param name="key">键的名称</param> /// <returns>键的值</returns> private string GetPrivateProfileString(string section, string key) { int nCapacity = 255; StringBuilder temp = new StringBuilder(nCapacity); int i = GetPrivateProfileString(section, key, "", temp, nCapacity, StartUpIniFileName); if (i < 0) return ""; return temp.ToString(); } /// <summary> /// 向Ini文件中写入值 /// </summary> /// <param name="section">应用程序</param> /// <param name="key">键的名称</param> /// <param name="value">键的值</param> /// <returns>执行成功为True,失败为False。</returns> public long WritePrivateProfileString(string section, string key, string value) { if (section.Trim().Length <= 0 || key.Trim().Length <= 0 || value.Trim().Length <= 0) return 0; return WritePrivateProfileString(section, key, value, StartUpIniFileName); } } }
附
除直接使用外,还可以写一个IniFile类,对读写方法进行调用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.IO; namespace 测试 { /// <summary> /// INI文件的操作类 /// </summary> public class IniFile { public string Path; public IniFile(string path) { this.Path = path; } #region 声明读写INI文件的API函数 [DllImport("kernel32")] private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); [DllImport("kernel32")] private static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath); [DllImport("kernel32")] private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath); #endregion /// <summary> /// 写INI文件 /// </summary> /// <param name="section">段落</param> /// <param name="key">键</param> /// <param name="iValue">值</param> public void IniWriteValue(string section, string key, string iValue) { WritePrivateProfileString(section, key, iValue, this.Path); } /// <summary> /// 读取INI文件 /// </summary> /// <param name="section">段落</param> /// <param name="key">键</param> /// <returns>返回的键值</returns> public string IniReadValue(string section, string key) { StringBuilder temp = new StringBuilder(255); int i = GetPrivateProfileString(section, key, "", temp, 255, this.Path); return temp.ToString(); } /// <summary> /// 读取INI文件 /// </summary> /// <param name="Section">段,格式[]</param> /// <param name="Key">键</param> /// <returns>返回byte类型的section组或键值组</returns> public byte[] IniReadValues(string section, string key) { byte[] temp = new byte[255]; int i = GetPrivateProfileString(section, key, "", temp, 255, this.Path); return temp; } } }
程序在调用IniFile类时需要实例化
//string path = Environment.CurrentDirectory + @"\Config.ini"; //指定ini文件的路径 string path = Application.StartupPath + @"\ver.ini"; //指定ini文件的路径 IniFile ini = new IniFile(path); string verValue = ini.IniReadValue("version", "ver");//读取ini文件中键值
备注
System.Environment.CurrentDirectory的含义是获取或设置当前工作路径,而Application.StartupPath是获取程序启动路径,表面上看二者没什么区别,但实际还是有区别。System.Environment.CurrentDirectory获取的当前工作路径不一定真的就是程序所在路径。比如说程序放在桌面上启 动,但是中间用了一个OpenFileDialog打开了D盘名为weisico的文件夹下的某一个文件,那么CurrentDirectory就变成 D:\weisico了,所以如果想再获取程序启动文件夹的某一个文件就没用了,但是Application.StartupPath就不会这样了,无论中间 打开了哪个盘的文件,启动路径都是和程序路径一致