Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2072|回复: 0
打印 上一主题 下一主题

为何微软不把 Windows 的默认字符集设置成 Unicode ?

[复制链接]

165

主题

269

帖子

957

积分

认证用户组

Rank: 5Rank: 5

积分
957
跳转到指定楼层
楼主
发表于 2017-1-19 19:36:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 firemail 于 2017-1-19 19:42 编辑

https://www.zhihu.com/question/24103924

Unicode已经发展了这么多年,已经成熟。且windows自己本身也完成了Unicode化,API也基本都提供了Unicode版本。UTF-8作为Unicode的一种流行的编码,但为何windows不把系统的默认字符编码设置成UTF-8,而仍然使用内码表来解决不同的编码问题。这不仅导致开发程序复杂,并且出现乱码也严重影响了windows的使用。


其实根本就没有“默认字符集”这种概念。Windows的内核就是用unicode编码的,而对于应用程序Windows允许使用不同的字符集。如果应用程序本身就是unicode的,那么一切ok;如果应用程序是non-unicode的,那么才需要用到“默认字符集”概念,但是请仔细看控制面板相关选项,这里的“默认字符集”其实是“non-unicode默认字符集”。就是说,这东西本身就是用于配置“非unicode程序”的,当然没法设置成unicode。
所以,正如 @时国怀所说的,都是兼容性惹的祸,因为微软不能说:“老子支持unicode了,以后不支持unicode的程序都给我滚粗。”只能撅着屁股让这些老掉牙的程序仍然可以运行,于是只好给他们提供一个“默认字符集”。

@赵冬毓 说的显然不是根本原因,在日本销售的Windows,“默认字符集”是shift-jis,难道也是为了遵循中国政府的规定?

是的,主要还是兼容性的原因。Unicode and Microsoft Windows NT 微软从WinNT 3.1就开始支持UTF-16了,但unicode和code page一直都是同时支持的。字符处理相关的API一般都有A和W两个版本。

msdn文档是鼓励新开发的程序使用unicode的。但在某些情况下,比如你的程序需要和不支持unicode的程序交互时,可能还是会需要用到code page。

Windows设置里的默认字符集,是指在字符不是unicode编码的情况下,Windows默认应该使用哪种字符集来处理。你的程序可以根据这个设置来选择相应的code page,处理非unicode编码,但它并不影响你在你的程序中使用unicode。

Windows内核中默认使用的是UTF-16,如果你写内核驱动就知道了,在内核里几乎都是以UTF-16的方式处理字符串的。

对于运行在应用层(用户态)的代码,Windows允许用户通过配置确定非Unicode字符的显示方式,可以是中文,也可以是BIG5,也可以是其它字符集。

为什么这么设计?因为是考虑到兼容性的问题,现在Windows7里,仍然能运行大量Windows 98时代的程序,WindowsXP里甚至能运行不少Windows3.x甚至更古老的程序,原因就是为了兼容性。

题主喜欢UTF-8,应该从Linux开发转过来的吧?Linux默认我记得是UTF-8(好像JSP也是?),UTF-8和UTF-16哪个更好我就不细说了,这方面的争论至今都没有结果。但是Windows可以把应用设置成UTF-16,之后的开发几乎没有太多的改变,我也没遇到过“这不仅导致开发程序复杂”的情况,至少C语言开发是这样的。所以,我看不出来UTF-16带来多少开发程序的不便。

为什么用UTF-16?好像UTF-16出现的比UTF-8要早一些,微软内核选择了UTF-16,再大改内核是非常困难的,大概是这样的。

Windows 在 16 位时代(版本1.0,2.x)和 16 / 32 位混合的时代初期(3.x),是不存在 Unicode 这个东西的。因此,早期的 Windows API 中,所有字符串都视为 ANSI 编码。Windows 3.0 中 / 日 / 韩文版引入了双字节字符集的概念,使得 Windows 开发中 ANSI 编码被称为所谓本地字符,并出现了 Windows 多区域支持(NLS National Language Support)。从 Windows NT 3.1 和开始,Windows 内部开始使用 UTF-16 作为字符串编码方式 (wchar_t),但是为了保证和以往 API 的兼容性,大多数和字符串有关的 API 函数都有 A 和 W 两个后缀的不同版本,A 代表传统的本地字符编码处理,W 代表UTF-16处理。在使用 C 语言进行 Windows 编程的时候,一般不直接使用后缀来选择不同版本的 API,而是通过在 <windows.h> 相关文件中通过处理宏 UNICODE 来选择。同时,NLS 也扩展到可以在多种内码之间互相转换,而 Unicode 的几种存储形式(UTF-16、UTF-8、UTF-7)也被 NLS 所支持。
虽然微软早已提供了原生的 UTF-16 支持,但是早期此支持仅仅在 Windows NT 系列操作系统中完整存在,而当时的主流是 16 / 32 位混合的 Windows 9x 系统,大多数 W 后缀的 API 调用都是不支持的,仅仅支持通过 NLS API 进行内码之间的转换。另外,同样为了保持和以往 API 的兼容性, wchar_t 类型的字符串在微软的 C 运行库里采用了一套不符合 ANSI C 标准的新函数(比如 sprintf -> swprintf, strcpy -> wcscpy)等来处理,不符合绝大多数 C 程序员的习惯。因此,当时很大一部分程序,甚至包括微软自己的 Office 系列都没有使用 Windows NT 的原生字符集 UTF-16,需要处理 UTF-16 时只是通过 MultiByteToWideChar 之类的 NLS 相关 API 进行转换。而为了兼容在这个传统下写出来的老应用程序,之后所有的 Windows 系统都同时存在和使用两套原生支持的字符集,NT 原生字符集(UTF-16) 以及本地字符集。当然,在现代的 Windows 编程规范中,都是明确推荐使用原生 UTF-16 字符集的。






回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-5-6 21:14 , Processed in 0.055490 second(s), 19 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表