在 Windows 应用中使用 UTF-8 代码页
使用 UTF-8 字符编码在 Web 应用和其他基于 *nix 的平台(Unix、Linux 和变体)之间实现最佳兼容性,最大程度地减少本地化 bug,并减少测试开销。
UTF-8 是国际化的通用代码页,可以编码整个 Unicode 字符集。 它在 Web 上广泛使用,并且是基于 *nix 的平台的默认代码页。
将进程代码页设置为 UTF-8
从 Windows 版本 1903(2019 年 5 月更新)起,可以使用打包应用的 appxmanifest 中的 ActiveCodePage 属性,或使用未打包应用的合成清单来强制进程使用 UTF-8 作为进程代码页。
注意
GDI 目前不支持为每个进程设置 ActiveCodePage 属性。 相反,GDI 默认为活动系统代码页。 若要将应用配置为通过 GDI 呈现 UTF-8 文本,请转到 Windows“设置”>“时间和语言”>“语言和区域”>“管理语言设置”>“更改系统区域设置”,然后选中“Beta:使用 Unicode UTF-8 获得全球语言支持”。 然后重新启动电脑,使更改生效。
你可以声明 ActiveCodePage 属性,并以早期 Windows 版本为目标或在这些版本上运行,但必须和往常一样处理旧代码页检测和转换。 使用最小目标版本 Windows 1903 版,进程代码页将始终为 UTF-8,因此可以避免使用旧代码页检测和转换。
注意
一个编码字符采用 1 到 4 个字节。 UTF-8 编码支持较长的字节序列(最多 6 个字节),但 Unicode 6.0 的最大码位 (U+10FFFF) 只需要 4 个字节。
示例
打包应用的 Appx 清单:
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
...
xmlns:uap7="http://schemas.microsoft.com/appx/manifest/uap/windows10/7"
xmlns:uap8="http://schemas.microsoft.com/appx/manifest/uap/windows10/8"
...
IgnorableNamespaces="... uap7 uap8 ...">
<Applications>
<Application ...>
<uap7:Properties>
<uap8:ActiveCodePage>UTF-8</uap8:ActiveCodePage>
</uap7:Properties>
</Application>
</Applications>
</Package>
未打包 Win32 应用的合成清单:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity type="win32" name="..." version="6.0.0.0"/>
<application>
<windowsSettings>
<activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
</windowsSettings>
</application>
</assembly>
注意
使用 mt.exe -manifest <MANIFEST> -outputresource:<EXE>;#1
从命令行向现有可执行文件添加清单。
-A 与 -W API
Win32 API 通常同时支持 -A 和 -W 变体。
-A 变体识别系统上配置的 ANSI 代码页并支持 char*
,而 -W 变体在 UTF-16 中运行并支持 WCHAR
。
到目前为止,Windows 一直强调“Unicode”-W 变体,而不是 -A API。 但是,最近发布的版本使用了 ANSI 代码页和 -A API 作为将 UTF-8 支持引入应用的一种方法。 如果 ANSI 代码页配置了 UTF-8,则 -A API 通常在 UTF-8 中运行。 此模型的优点是,支持使用 -A API 生成的现有代码,而无需进行任何代码更改。
代码页转换
由于 Windows 在 UTF-16 (WCHAR
) 中以本机方式运行,因此你可能需要将 UTF-8 数据转换为 UTF-16(反之亦然),以便与 Windows API 进行互操作。
MultiByteToWideChar 和 WideCharToMultiByte 使你可以在 UTF-8 和 UTF-16 (WCHAR
)(以及其他代码页)之间进行转换。 如果旧版 Win32 API 只能理解 WCHAR
,这将特别有用。 这些函数允许你将 UTF-8 输入转换为 WCHAR
,以传递到 -W API,然后在必要时将结果转换回来。
使用这些函数时,请使用 dwFlags
或 0
的 MB_ERR_INVALID_CHARS
,并将 CodePage
设置为 CP_UTF8
,否则会出现 ERROR_INVALID_FLAGS
。
注意
仅当在 Windows 版本 1903(2019 年 5 月更新)或更高版本上运行,且上述“ActiveCodePage”属性设置为“UTF-8”时,CP_ACP
才等于 CP_UTF8
。 否则,它采用旧的系统代码页。 建议显式使用 CP_UTF8
。