ini 文件读写需通过 pinvoke 调用 windows api(如 getprivateprofilestring),c# 标准库不支持;仅限 windows,文件路径须绝对,编码须为 ansi 或 utf-16 le(带 bom),跨平台应优先选用 appsettings.json 或 iniparser 等替代方案。

INI 文件没有内置支持,得靠 PInvoke 调用 Windows API
C# 标准库不提供原生的 INI 文件读写能力。很多人以为 ConfigurationManager 或 IConfiguration 能直接处理 .ini,其实不能——它们只认 .config、appsettings.json 这类格式。GetPrivateProfileString 和 WritePrivateProfileString 是 Windows API 提供的唯一直接支持方式,必须用 PInvoke 封装。
- 仅限 Windows 平台;跨平台项目(如 .NET 6+ Linux/macOS)会直接失败
- 调用前需确保 INI 文件路径是绝对路径,相对路径容易因工作目录变化而读不到
- 函数对 section 名和 key 名大小写不敏感,但值内容保留原始大小写
- 如果文件不存在,读取时返回空字符串,写入时会自动创建文件
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern uint GetPrivateProfileString(
string lpApplicationName,
string lpKeyName,
string lpDefault,
StringBuilder lpReturnedString,
uint nSize,
string lpFileName);
读取 INI 时最常见的三个错误现象
不是代码写错,而是对 API 行为理解偏差导致的“读不出来”:
-
GetPrivateProfileString返回 0:通常是因为传了 null 或空字符串给lpApplicationName或lpKeyName,而不是“没找到” - 读到空值:检查文件编码——API 只正确处理 ANSI 或 UTF-16 LE(带 BOM),UTF-8 无 BOM 的文件会乱码或全空
- 读到旧值:Windows 会缓存 INI 内容,尤其在快速连续读写时;实际无需手动刷新,但若调试中反复修改文件又读不到新值,重启进程最可靠
写入 INI 必须注意换行与节头格式
WritePrivateProfileString 看似简单,但生成的文件格式直接影响其他工具(比如记事本、旧版 VB6 程序)能否识别:
- 它不会自动添加空行分隔 section,也不会补全缺失的
[section]头——你写哪个 key,它只动那一行,其余全不动 - 写入空字符串
""会删除该 key;写入null会导致 PInvoke 异常 - 写入含等号
=的值会被截断(API 把第一个=当作键值分隔符),要提前替换为其他占位符再写 - 写入后文件编码保持原样,不会转成 UTF-8;若原文件是 ANSI,新写入的中文可能显示为乱码(取决于系统默认 ANSI 代码页)
替代方案比硬刚 API 更靠谱的场景
如果你只是想存几组配置、不强依赖 Windows 原生 INI 格式,真没必要绑死 PInvoke:
- 用
File.ReadLines+ 正则手动解析:适合只读、结构简单、且需要跨平台的场景;缺点是没法原子写入、不支持注释保留 - 引入第三方包如
IniParser(NuGet):能处理 UTF-8、注释、空行,还支持对象映射;但它内部仍是文本解析,不是调用系统 API - 改用
appsettings.json:.NET Core/5+ 默认配置机制,热重载、类型安全、环境隔离都现成;唯一代价是得说服协作方接受格式变更
真正绕不开原生 INI 的情况,基本只剩对接老系统、硬件 SDK 或客户强制要求 INI 文件名+格式的交付场景。其他时候,花半小时改用 JSON,后面省下的排查时间远不止半小时。










