为什么不允许UTF-8作为"ANSI"代码页?

dan*_*n04 18 windows utf-8 mbcs

Windows _setmbcp函数允许任何有效的代码页...

(UTF-7和UTF-8除外,不支持)

好的,不支持UTF-7是有道理的:字符具有非唯一的表示形式,并且会带来复杂性和安全风险.

但为什么不是UTF-8?

据我所知,Windows API函数的"ANSI"版本将其参数转换为UTF-16,调用等效的"W"函数,并将输出中的任何字符串转换为"ANSI".这就是我一直在手动做的事情.那么为什么Windows不能为我做呢?

Dea*_*ing 9

"ANSI"代码页基本上是传统的:Windows 9X时代.无论如何,所有现代软件都应该是Unicode(即UTF-16).

基本上,当最初设计Ansi代码页的东西时,UTF-8甚至没有被发明,因此对多字节编码的支持是相当偶然的(即大多数Ansi代码页是单字节的,除了一些东亚代码页这是一个或两个字节).当所有新开发都应该以UTF-16完成时,添加对"正确"多字节编码的支持可能被认为是不值得的.

  • 我同意所有新开发都应该是*Unicode*.但我有理由建议使用UTF-8而不是UTF-16.(1)我的团队写了一百万行不支持Unicode的代码,然后才有人对它进行了诅咒,现在将所有这些基于字符的字符串更改为基于wchar_t的字符串将是一项巨大的努力.(2)我们计划将我们的产品移植到Linux,而UTF-8往往是首选. (19认同)
  • 从 Windows 版本 1903(2019 年 5 月更新)开始,您可以[使用 UTF-8 代码页](https://learn.microsoft.com/en-us/windows/uwp/design/globalizing/use-utf8-code -页) (3认同)

phu*_*clv 6

原因与jamesdlin 的答案及其下面的评论中所说的完全一样:MBCS 与 Windows 中的 DBCS 相同,并且某些函数不适用于长度超过 2 个字节的字符

\n
\n

微软表示 UTF-8 语言环境可能会破坏一些功能功能,因为它们被编写为假定每个字符使用的多字节编码不超过 2 个字节,因此具有更多字节的代码页(例如 UTF-8(以及 GB 18030、cp54936))无法使用被设置为区域设置。

\n

https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows#UTF-8

\n
\n

因此,在读/写等函数中允许使用 UTF-8,但在用作语言环境时则不允许使用 UTF-8

\n
\n

不过微软终于解决了这个问题,所以现在我们可以使用 UTF-8 作为语言环境。事实上,MS 甚至-A再次开始推荐 ANSI API (),而不是像以前那样推荐 Unicode ( -W) 版本。MSVC 中有一些新选项:/execution-charset:utf-8/utf-8设置字符集,或者您也可以在 UWP 应用程序的 appxmanifest 中设置 ActiveCodePage 属性

\n

自 Windows 10 Insider Build 17035 起,在引入这些选项之前,还添加了“Beta:使用 Unicode UTF-8 进行全球语言支持”复选框,用于将区域设置代码页设置为 UTF-8

\n

Beta:使用 Unicode UTF-8 提供全球语言支持

\n

要打开该对话框,请打开“开始”菜单,键入“区域”,然后选择区域设置 > 其他日期、时间和区域设置 > 更改日期、时间或数字格式 > 管理

\n

启用后,您可以调用setlocale()更改为 UTF-8 语言环境:

\n
\n

从 Windows 10 内部版本 17134(2018 年 4 月更新)开始,通用 C 运行时支持使用 UTF-8 代码页。这意味着char传递给 C 运行时函数的字符串将需要 UTF-8 编码的字符串。要启用 UTF-8 模式,请在使用 时使​​用“UTF-8”作为代码页setlocale。例如,setlocale(LC_ALL, ".utf8")将使用当前默认的 Windows ANSI 代码页 (ACP) 作为区域设置,并使用 UTF-8 作为代码页。

\n

UTF-8 支持

\n
\n

您也可以在较旧的 Windows 版本中使用它

\n
\n

要在 Windows 10 之前的操作系统(例如 Windows 7)上使用此功能,您必须使用应用程序本地部署或使用 Windows SDK 版本 17134 或更高版本进行静态链接。对于 17134 之前的 Windows 10 操作系统,仅支持静态链接。

\n
\n

也可以看看

\n\n


Rem*_*eau 5

_setmbcp()是VC++ RTL函数,而不是Win32 API函数.它只影响RTL解释字符串的方式.它对Win32 API A函数没有任何影响.当他们在W内部调用对方时,A函数总是使用MultiByteToWideChar()WideCharToMultiByte()指定代码页0(CP_ACP)以使用系统默认的Ansi代码页进行转换.


jam*_*lin 5

微软国际化专家迈克尔卡普兰试图在他的博客上回答这个问题

基本上他的解释是,尽管 Windows API 函数的“ANSI”版本旨在处理不同的代码页,但历史上有一个隐含的期望,即字符编码每个代码点最多需要两个字节。UTF-8 不符合这种期望,现在更改所有这些功能需要进行大量测试。

  • @evoskuil 是的,CP_UTF7 和 CP_UTF8 已经可用很长时间了。但是,它们不能用作*默认* 代码页。它们仅用于`MultiByteToWideChar`/`WideCharToMultiByte`。是的,DBCS 是 MBCS 的一种形式,但在我引用的页面的更深处,它明确指出“MBCS 始终表示 DBCS。不支持超过 2 个字节的字符集。” 在 http://msdn.microsoft.com/en-us/library/b6ewb9fy.aspx 上,它指出:“使用 MBCS,字符的大小可以为 1 或 2 个字节。” (3认同)
  • 他们最终使得使用 UTF-8 作为语言环境成为可能 (2认同)