已经有一些问题与此问题相关。我认为我的问题略有不同,因为我没有实际的问题,我只是出于学术兴趣而问。我知道 Windows 的 UTF-16 实现有时与 Unicode 标准相矛盾(例如排序),或者更接近旧的 UCS-2 而非 UTF-16,但出于简单起见,我将在这里保留“UTF-16”术语。
背景:在 Windows 中,一切都是 UTF-16。无论您正在处理内核、图形子系统、文件系统还是其他任何内容,您都需要传递 UTF-16 字符串。没有 Unix 意义上的区域设置或字符集。为了与 Windows 的中古版本兼容,有一个叫做“代码页”的东西,它已经过时,但仍然得到支持。据我所知,只有一种正确且不过时的函数可以将字符串写入控制台,即 WriteConsoleW
,它接受一个 UTF-16 字符串作为参数。对于输入流也有类似的讨论,但我将忽略它。
然而,我认为这代表了 Windows API 的设计缺陷:有一个通用函数可以用于写入所有流对象(文件、管道、控制台等),名为 WriteFile
,但这个函数是面向字节的,并不接受 UTF-16 字符串。文档建议将 WriteConsoleW
用于控制台输出,这是面向文本的,而将 WriteFile
用于其他所有内容,这是面向字节的。由于控制台流和文件对象都由内核对象句柄表示,并且控制台流可以被重定向,因此您必须针对每个写入标准输出流的操作调用一个函数来检查句柄代表控制台流还是文件,破坏了多态性。另一方面,我确实认为 Windows 在文本字符串和原始字节之间的分离(这反映在许多其他系统中,例如 Java 或 Python)在概念上优于 Unix 的 char*
方法,后者忽略编码并不区分字符串和字节数组。
我认为普遍存在的问题(这不容易解决)是所有库都假定所有流都是面向字节的,并在此基础上实现面向文本的流。然而,我们看到Windows在操作系统级别上确实有特殊的面向文本的流,但库无法处理这个问题。因此,在任何情况下,我们必须对所有标准库进行重大更改。一种快速而简单的方法是将控制台视为只接受一种编码的特殊面向字节的流。这仍然需要绕过C和C++标准库,因为它们没有实现
WriteFile
/WriteConsoleW
切换。这正确吗?