Windows 中的 UTF-8 - INI 文件






4.94/5 (6投票s)
如何在 Windows INI 文件中处理 UTF-8
引言
在我之前的文章“在 Windows 中使用 UTF-8”中,我展示了如何仅使用两个函数 utf8::narrow
和 utf8::widen
来处理 UTF-8。 对于一般的文件 I/O,您只需要将文件名从 UTF-8 转换为 UTF-16,所有的读写函数保持不变
FILE *f = utf8::fopen (u8"ܐܪܡܝܐ.txt", "w");
fputs (u8"This text is in Aramaic ܐܪܡܝܐ", f);
fclose (f);
有一种情况不属于这些规则的涵盖范围:INI 文件,在 Microsoft 的术语中也被称为“配置文件”。 尽管有许多其他存储应用程序设置的方法,但 INI 文件仍然被广泛使用,原因要么是兼容性,要么是它们易于使用。
问题是用于读写 INI 文件的基本 Windows API 调用 GetPrivateProfileString
和 PutPrivateProfileString
在一个 API 调用中结合了文件名和要读写的信息。 例如,这是 GetPrivateProfileStringW
函数的签名
DWORD GetPrivateProfileStringW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize,
LPCWSTR lpFileName
);
如果我们使用 utf8::widen
函数来转换所有 UTF-8 字符串,最终得到的 INI 文件将包含 UTF-16 字符。
解决方案是完全忘记 Windows API 函数,并构建我们自己的实现来访问 INI 文件。 这绝不是您可以找到的 INI 文件的唯一实现。 有关实现的列表,您可以查看 Wikipedia 页面。 其中一些可能有点过分炒作; 其中一个项目声称是“用 C 编写的终极且最一致的 INI 文件解析器库”。 我唯一的声明是,我的实现努力与原始 Windows API 尽可能兼容。
因此,您将找不到对文件格式的任意扩展,并且我进行了大量测试以识别不同的极端情况。 这是我通过尝试对原始 Windows API 进行不同组合的调用而发现的规则
- 只有以分号开头的行是注释行(哈希在 Windows API 中不被视为注释)。
- 没有尾随注释; 等号“=”之后的任何内容都是键值的一部分。
- 前导和尾随空格都会从返回的字符串和参数中删除。
与 Windows API 相比,唯一的更改是
- 行长默认为 1024 (
INI_BUFFER_SIZE
值),而 Windows 将其限制为 256 个字符。 - 没有路径的文件在当前目录中,而 Windows 将它们放在 Windows 文件夹中。
实现
INI 文件被实现为 IniFile
对象。 像在下面的代码中一样,基本成员函数 IniFile::GetString
和 IniFile::PutString
允许您在 INI 文件中读写设置
utf8::IniFile test ("test.ini");
test.PutString ("key1", "value11", "section1");
string val = test.GetString ("key1", "section1");
原始 Windows API 仅处理 INI 文件的两种数据类型:字符串和整数。
(GetPrivateProfileString
和 GetPrivateProfileInt
函数)。 我认为将这些函数扩展到其他数据类型并添加一些实用函数很有用。 这不是文件格式的扩展; 这只是用于访问这些文件的 API 的扩展。 以下是其中一些功能
PutInt
和GetInt
用于整数值PutDouble
和GetDouble
用于浮点值PutBool
和GetBool
用于布尔变量(读取时,代码理解诸如“on”或“0”或“OFF”之类的东西)PutColor
和GetColor
用于 RGB 颜色表示PutFont
和GetFont
用于保存和检索字体设置HasKey
和HasSection
用于检查 INI 文件中是否存在键或节
查看代码时,有几个有趣的点。
INI 文件没有内存缓冲。 所有内容都尽快写入磁盘。 这是一个设计决定,因为
- 这就是 Windows 所做的,我想尽可能兼容,而且
- 当应用程序崩溃或以其他方式意外结束时,参数没有被保存,这非常烦人。 这种缺点是 INI 文件的效率降低,但它们并非旨在成为通用数据文件。
此外,每次在 INI 文件中写入一个键时,都会重新写入整个文件; 正如我所说,效率不是一个设计目标。
结论
本文中显示的代码使使用 UTF-8 编码在 INI 文件中保留应用程序设置变得容易。
本系列关于 Windows 中 UTF-8 的文章到此结束。 本系列的前两篇文章是
作为参考,本文包含的代码也包含前几篇文章的代码。
历史
- 2020 年 4 月 2 日:初始版本