【问题标题】:What limitations does the Windows console have regarding Unicode?Windows 控制台对 Unicode 有哪些限制?
【发布时间】:2016-10-18 20:22:09
【问题描述】:

可以使用WriteConsoleW 函数将Unicode 字符写入Windows 控制台。在我的 Windows 7 机器上,控制台似乎不支持基本多语言平面之外的字符。此外,组合字符显示在基本字符之后,而不是实际组合。

这些限制是否也存在于更高版本的 Windows 中? Windows 控制台中的 Unicode 是否还有其他限制?

【问题讨论】:

  • Windows 通过创建窗口的方式知道窗口使用什么编码 - CreateWindowsExA (ansi) 或 CreateWindowsExW (Unicode)。 Windows 会自动从发送窗口转换为接收窗口。因此,将 Unicode 字符发送到 Ansi 窗口,Ansi 窗口会接收从 Unicode 转换而来的 Ansi 字符。控制台窗口使用 DOS 并发生相同的转换。所以如果可能,writeConsoleW 将被转换为 Dos 字符。
  • 但是控制台可以使用CHCP 命令转换为任何代码页,如果cmd 启动cmd /u,内部命令可以输出Unicode。见chcp /?cmd /?
  • Windows 控制台不支持完整的UTF-16。 “It's limited to UCS-2, i.e. limited to characters in the basic multilingual plane (BMP)”。引用:@eryksun 2015 年 2 月 23 日 6:22
  • 字符在控制台窗口中的显示方式取决于控制台窗口使用的字体以及该字体支持的整个 Unicode 表中的字符集。
  • 不知道为什么这个问题收到-1,对我来说似乎完全有效。我只是想知道同样的问题,来这里澄清一下。

标签: windows unicode cmd console


【解决方案1】:

我在my answer to a different question写了部分答案;这是一个全面披露的好地方。我的背景:我保留了最广泛的 console font which fully supports Windows (这是对 Unifont 的非常深刻的重写,并添加了 DejaVu 的元素)。

我从其他答案中已经提到的限制开始:

  • 每个单元格包含 16 位字符数据。换句话说:仅显示 UCS-2 代码点。 (特别是,对于 BMP 之外的字符,它的“分解为 UCS-2”会改为显示,使用代理字符。)

  • 仅支持简单的文本渲染。即使使用 TTF 字体,控制台也不会考虑字体的高级“功能”。高级排版(连字等),甚至用于组成字符的字形或从右到左的脚本¹⁾(在 LtR 环境中)都不会按预期工作。

        ¹⁾ 应用程序应该重新排列字符以获得正确的双向渲染。

字体过滤

其他限制是由于控制台的字体过滤造成的。字体必须非常特殊才能被控制台接受(显示在字体选择对话框中,并且此选择“有效”¹⁾)。

    ¹⁾ 我不记得是否可以显示字体,但无法选择(我对这种情况有模糊的记忆,但不能相信这种记忆)。

  • 字体必须标记为等宽字体。由于应用程序的期望,²⁾此类字体必须具有相同宽度的所有字形。

        ²⁾后一种条件仅在想要在控制台之外使用字体时才相关。原则上,控制台不检查字形的宽度。但是,每个字形都显示为好像它具有“默认宽度”。在许多(全部?)情况下,只会显示“默认边界框”内的字形部分。我找不到任何技巧来规避这个限制。

  • 在 Windows 的非东亚版本中,字体不能声称它支持 4 个东亚代码页中的任何一个。³⁾

        ³⁾ 请注意,这只是字体标题的限制声称 — 标题中只有 4 位。字体可能存在这些语言的字形,并且它们会显示得很好 — 只要字体不要求支持。有问题的代码页(在标题的 OS/2⫽字符集部分)是 932、936、949、950(JIS、简体中文、韩语 Wansung、繁体中文)。

字体渲染中的错误

  • 虽然 Windows 的控制台不支持Underline 属性(DBCS codepages 除外),但在屏幕字符 bbox 的大小时会考虑字体标题的“Underline position”字段是计算出来的。这可能会导致字体出现意外的纵横比,和/或预期会“连接在一起”的字形之间出现中断。

  • 控制台对“不支持的字符”的替换字形非常挑剔。我找不到如何使这样的字形与U+0000 和/或U+0001 的字形共存。 (如果控制台在字体中找到后两个字形之一,它会忽略替换字形。)

  • (这是一个非常模糊的错误;它需要非常技术性的讨论。)替换字形的另一个问题是字符U+30FB·(为什么?!)。如果该字符存在于字体中,则该字符的字形将用作替换字形 — 但仅用于 PUA 中缺少的字符!

基本上就是这样!我没有发现任何其他限制。

【讨论】:

  • U+30FB(片假名中点)是通过MultiByteToWideChar解码时代码页932(日语)的替换字符。我认为对于大多数代码页来说,它是“?”相反,除了 UTF-8 (65001) 使用 U+FFFD。可通过GetCPInfoExW查询。如果应用程序通过WriteFileWriteConsoleA 等ANSI API 将无效的字节序列写入屏幕缓冲区,则会发生这种替换。顺便说一句,我不知道这个默认字符与 GDI 对 PUA 的 默认字形 的呈现有何关系。
【解决方案2】:

Windows 控制台仅限于基本多语言平面

您指向WriteConsole function 的链接没有说明可用的控制台字符:

  • lpBuffer [in] 指向 缓冲区 的指针,其中包含要写入控制台屏幕缓冲区的字符。

但是那个缓冲区是什么?对 writeconsole lpbuffer 结构 的简单 Google 搜索提供了到 CHAR_INFO structure 的(间接)链接:

语法 (C++)

typedef struct _CHAR_INFO {
  union {
    WCHAR UnicodeChar;
    CHAR  AsciiChar;
  } Char;
  WORD  Attributes;
} CHAR_INFO, *PCHAR_INFO;

但是WCHAR UnicodeChar 是什么?同样,对 windows wchar 的简单 Google 搜索会提供指向 Windows Data Types 的链接:

  • WCHAR 16 位 Unicode 字符。有关详细信息,请参阅Character Sets Used By Fonts。此类型在WinNT.h 中声明如下:typedef wchar_t WCHAR;

最后,上面的Character Sets Used By Fonts 链接给出了下一个最终结果:Windows 控制台仅限于基本多语言平面,即16 位 Unicode 子集:

Unicode 字符集

…为了解决多种编码方案的问题,Unicode 制定了数据表示标准。 16 位字符 编码方案,Unicode 可以表示 65,536 (2^16) 个字符,其中 足以包括当今计算机商务中的所有语言,以及 作为标点符号、数学符号和扩展空间。 Unicode 为每个字符建立一个唯一的代码,以确保 字符翻译总是准确的。

【讨论】:

  • 您链接到了错误的函数。 CHAR_INFOWriteConsoleOutput 使用,同样KEY_EVENT_RECORDWriteConsoleInput 使用。 Character Sets Used By Fonts 没有提到控制台,而且它已经过时了。除了控制台,Windows 现在还支持 UTF-16。
  • Unicode 不是 16 位字符编码方案,尽管它最初是这样设想的。它是一个 21 位字符方案,具有多种编码:UTF-8 和 UTF-16 是最常见的,但也存在 UTF-7、UTF-32 和其他编码。 Windows 控制台支持 UCS-2,它类似于 UTF-16,只是它是 Unicode 的 子集。由于 UCS-2 是固定宽度的 16 位,因此 Windows 控制台“仅基本多语言平面”的限制来自于此。希望这有助于消除任何困惑!
猜你喜欢
  • 2016-12-13
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
相关资源
最近更新 更多