Windows和Unix的Unicode实现的差别

rights:http://blog.chinaunix.net/uid-20674485-id-1577694.html

Windows
       首先介绍Windows。
       早期的Windows系统,例如Windows 1.0、Windows 2.0、Windows 3.0、 Windows 3.1等系统,是不支持Unicode编码的,而是使用ANSI编码(即兼容ASCII的任何本地编码)。即使在Windows 9x系列系统中,也不支持Unicode编码,只是在文件系统中使用UTF-16编码(例如FAT16/FAT32的长文件名),系统核心还是使用ANSI编码。
       微软真正开始实现Unicode编码的是Windows NT操作系统。后来的Windows 2000/XP/Vista都是基于Windows NT内核的。
       微软创造Windows NT系统的最初目的是抢占服务器和工作站市场,微软公司从数字设备公司(Digital Equipment Corporation)雇佣了一批人员来开发这个新系统,其竞争对手为Unix系列操作系统。
       由于Windows NT是全新设计的系统,没有历史累赘,一开始就决定使用Unicode编码作为默认编码。于是,NT系统内核强制一定要使用Unicode编码。那时,Unicode只有一种形式,就是UTF-16,所以Windows的Unicode实现方案是使用UTF-16。这样就决定NT的内核只能使用一种字符串,就是UTF-16字符串,用C语言来说,就是wchar_t类型的字符串,每个字符占用2个字节。
       文件系统方面,微软扩展了FAT16/32,增加了长文件名功能;还有就是重新设计了NTFS文件系统。FAT16/FAT32在DOS下,只能使用8+3的文件名长度,使用的是ANSI编码。在Windows下,通过使用多个目录项来实现长文件名,并强制性地把长文件名的编码设定为Unicode的UTF-16编码,这样有利于国际化。NTFS文件系统专门为NT系统设计,自然也是使用UTF-16编码。
       在应用层里,Windows NT在有关字符与字符串有关的方面均提供了两套API。分别是ANSI和Unicode两套API。
例如名为MessageBox函数是一个显示消息框的API函数,包含头文件windows.h即可使用。MessageBox实际是两个函数的合称,分别是MessageBoxA和MessageBoxW,前者是ANSI版本,需传递的参数是char字符串,后者是Unicode版本,需传递的参数是wchar_t字符串。
       如使用MessageBoxA函数,系统在处理ANSI字符串时,首先根据codepage的设置,把ANSI字符串转换为UTF-16字符串,再把转换后的UTF-16字符串传递入系统内部处理。如使用MessageBoxW函数,则不需要再进行字符编码转换操作,处理速度会更快。
       Codepage是一种本地化ANSI字符串是实现方法,例如简体中文使用codepage-936,编码是GBK,繁体中文使用codepage-950,编码是Big-5。
       出现乱码的情况,是codepage使用错误。例如把Big-5的程序放到简体中文系统里面使用,就会出现乱码。乱码是在把ANSI转换成Unicode时出现的,如果codepage不匹配,就会产生乱码现象。
       在Windows下编程,最好直接使用Unicode编程,这样可以避免使用ANSI字符串而在不同语系的Windows系统里产生乱码现象,更因为少了字符串转换这步,可以加快程序运行速度。
Unix类
       Unix产生与1969年,那时还没有出现Unicode呢,ASCII编码是那时最完善的编码。那时硬件十分昂贵,就连使用两个字节来表示一个字符也是不敢想象的。所以Unix系统是使用单字节编码来表示文字字符,其内核并没有强制使用那种字符编码。
       也就是说,Unix类的系统中,在内核里,是不会管你字符编码是什么的,也不会管你会不会发生乱码,只要是以0结尾的字节串,都是有效的字符串。
       由于最初Unix的这种设计,以及大量使用了流技术,这导致Unix无法使用UTF-16字符编码,因为UTF-16是双字节的。
       Unicode组织后来设计了UTF-8方案,是一种8位的Unicode编码方法。UTF-8的出现使得Unix类系统支持Unicode成为可能。这样Unix类的系统就不需要进行重新设计,而通过UTF-8来实现Unicode支持。
       Linux是一个Unix的复制品,Unix的这种设计也复制到了Linux。
       文件系统方面,Unix类系统也没有强制用户使用UTF-8编码,只要是ASCII兼容的字符编码都可以用,这样有好处也有坏处,好处是系统内核不必理会编码问题,坏处是会造成编码混乱。
在 UTF-8 发布之前,Linux 用户使用各种不同特定语言的扩展 ASCII,像欧洲用户用 ISO 8859-1 或 ISO 8859-2,希腊用户使用 ISO 8859-7,俄罗斯用户使用 KOI-8 / ISO 8859-5/CP1251(西里尔字母)。这使得数据交换出现了很多问题,并且需要为这些编码之间的差异编写应用软件。这种语言支持是不完善的,而且数据交换没有经过测试。Linux 主要的发行商和应用程序开发者正致力于让主要以 UTF-8 格式表示的 Unicode 成为 Linux 中的标准。
       在Unix下使用UTF-8,必须设置locale来实现支持UTF-8。例如在bash中使用命令:
export  LANG=zh_CN.UTF-8
处理多字节字符代码序列的函数行为依赖于当前语言环境的 LC_CTYPE 类别;它确定了依赖语言环境的多字节编码。值 LANG=zh_CN(简体中文)会导致输出按 GB-2312 编码被格式化。值 LANG=zh_CN.UTF-8 会把输出格式化成 UTF-8。语言环境设置会导致 printf 中的 %ls 格式说明符调用 wcsrtombs() 函数以便于将宽字符的参数字符串转换成依赖语言环境的多字节编码。
       Unix通过UTF-8来实现Unicode,只是实现而已,并没有根本消除乱码现象,由于UTF-8的引入,使得字符编码类型又增加了一种,使乱码的可能性更加剧了。只能靠大家全部自觉设置locale为UTF-8了。(但是这不是强制性的约定,例如我本人就不喜欢UTF-8,还是把locale设置为GBK)
比较
(1)Windows采取的方案是UTF-16,系统在内核里面强制使用UTF-16编码,甚至连文件系统也必须是UTF-16字符编码格式,应用层可以不需要理会codepage设置而直接使用UTF-16,也可以把ANSI字符串转换为UTF-16字符串再调用内核。
(2)Unix类的系统采取的方案是UTF-8,内核不理会字符编码的具体实现,Unicode的实现是在应用层上实现,主要是通过libc的locale功能进行实现。必须把locale设置为UTF-8才可以使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值