C# 读写 INI 配置文件类详解

顾言
顾言
发布时间:2026-10-14| 5人浏览过
原创

在使用 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# 配置管理技巧的资料请关注本站其它相关文章!
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。