C# 读写 INI 配置文件类详解
在使用 C# 进行桌面应用或旧系统对接开发时,经常需要处理传统的 INI 配置文件。由于 .NET Framework 标准库并未直接提供高效的 INI 读写类,通常借助平台调用服务(P/Invoke)调用 Windows 内核函数的 kernel32.dll 来实现。本文将展示一个封装完整的 INIHelper 类,涵盖单个键值读写、全文件节点遍历以及特定节点下所有配置项的提取功能。
C# 编写 INI Helper 类
实现 INI 文件操作的本质是利用操作系统底层的配置管理接口。我们需要在 C# 中声明相应的非托管函数签名,并通过 [DllImport] 特性将其映射到系统动态链接库中。
第1步:定义底层 API 接口
首先,引入必要的命名空间并声明四个核心 Windows API 函数。这些函数负责实际的磁盘读写工作:
WritePrivateProfileString:将字符串写入指定的节点(Section)和键(Key)。GetPrivateProfileString:从指定路径读取某个键的值。GetPrivateProfileSectionNames:获取 INI 文件中所有的 Section 名称列表。GetPrivateProfileSection:获取指定 Section 下所有的 Key 和 Value 数据块。
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections;
public class INIHelper
{
// 写入配置
[DllImport("kernel32.dll", EntryPoint = "WritePrivateProfileString", CharSet = CharSet.Ansi)]
public static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
// 读取单个配置
[DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileString", CharSet = CharSet.Ansi)]
public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
// 获取所有节点名
[DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileSectionNames", CharSet = CharSet.Ansi)]
public static extern int GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer, int nSize, string filePath);
// 获取节点下所有内容
[DllImport("KERNEL32.DLL ", EntryPoint = "GetPrivateProfileSection", CharSet = CharSet.Ansi)]
public static extern int GetPrivateProfileSection(string lpAppName, byte[] lpReturnedString, int nSize, string filePath);
}
第2步:实现单键值对的读写方法
对于大多数场景,只需修改或获取特定的配置项。下面定义了静态方法 Write 和 Read,简化了参数传递过程。
/// <summary>
/// 向INI写入数据。
/// </summary>
public static void Write(string Section, string Key, string Value, string path)
{
WritePrivateProfileString(Section, Key, Value, path);
}
/// <summary>
/// 读取INI数据。
/// </summary>
public static string Read(string Section, string Key, string path)
{
StringBuilder temp = new StringBuilder(255);
// 获取值,如果失败则返回默认空字符串
GetPrivateProfileString(Section, Key, "", temp, 255, path);
return temp.ToString();
}
第3步:获取文件中的所有 Section 名称
当需要扫描配置文件结构时,可以使用 GetAllSectionNames。该函数分配一块内存缓冲区接收系统返回的双Null字符分隔的字符串列表,并解析为字符串数组。
/// <summary>
/// 读取ini里面所有的节
/// </summary>
public static int GetAllSectionNames(out string[] sections, string path)
{
int MAX_BUFFER = 32767;
IntPtr pReturnedString = Marshal.AllocCoTaskMem(MAX_BUFFER);
int bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, path);
if (bytesReturned == 0)
{
sections = null;
return -1; // 无节点或错误
}
// 将指针转换为字符串,注意尾部有一个终止的 Null 字符需剔除
string local = Marshal.PtrToStringAnsi(pReturnedString, (int)bytesReturned);
Marshal.FreeCoTaskMem(pReturnedString); // 释放内存
// 去掉末尾的 \0 并进行分割
sections = local.Substring(0, local.Length - 1).Split('\0');
return 0;
}
第4步:提取指定节点下的所有 Key 和 Value
若需批量导出某个 Section 下的配置映射,可使用 GetAllKeyValues。此方法读取原始字节流并尝试按 “=” 号拆分键值对。
/// <summary>
/// 得到某个节点下面所有的key和value组合
/// </summary>
public static int GetAllKeyValues(string section, out string[] keys, out string[] values, string path)
{
byte[] b = new byte[65535];
GetPrivateProfileSection(section, b, b.Length, path);
// 使用当前 ANSI 编码解析字节数组
string s = System.Text.Encoding.Default.GetString(b);
string[] tmp = s.Split((char)0);
ArrayList result = new ArrayList();
foreach (string r in tmp)
{
if (!string.IsNullOrEmpty(r))
result.Add(r.Trim());
}
keys = new string[result.Count];
values = new string[result.Count];
for (int i = 0; i < result.Count; i++)
{
string itemStr = result[i].ToString();
string[] item = itemStr.Split(new char[] { '=' });
if (item.Length == 2)
{
keys[i] = item[0];
values[i] = item[1];
}
else if (item.Length == 1)
{
keys[i] = item[0];
values[i] = "";
}
else
{
keys[i] = "";
values[i] = "";
}
}
return 0;
}
注意事项与维护建议
上述代码主要依赖系统的 ANSI 编码处理机制。在涉及中文等非 ASCII 字符的路径或内容时,CharSet.Ansi 可能会受到系统区域设置的影响。如果发现读取到的中文内容为乱码,可以考虑检查系统环境变量或尝试调整 GetPrivateProfileString 的行为(注:.NET Core / .NET 5+ 跨平台版本可能需要不同的处理方式,因为某些 Linux/macOS 版本并不直接提供该 API)。
此外,由于该方法直接操作文件 I/O,建议在多线程环境下加锁,或者确保写入操作的原子性,防止配置丢失。
以上就是 C# 实现 INI 文件读写类的详细内容,更多关于 C# 配置管理技巧的资料请关注本站其它相关文章!本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













