zoukankan      html  css  js  c++  java
  • 确定Windows XP到底是UCS2的还是UTF16的

    一般认为Windows下以16bit表示的Unicode并不是UTF-16,而是UCS-2。UCS-2是一种编码格式,同时也是指以一一对应关系的Unicode实现。在UCS-2中只能表示U+0000到U+FFFF的BMP(Basic Multilingual Plane ) Unicode编码范围,属于定长的Unicode实现,而UTF-16是变长的,类似于UTF-8的实现,但是由于其字节长度的增加,所以BMP部分也做到了一一对应,但是其通过两个双字节的组合可以做到表示全部Unicode,表示范围从U+0000 到 U+10FFFF。关于这一点,我在很多地方都看到混淆了,混的我自己都有点不太肯定自己的说法了,还好在《UTF-16/UCS-2》中还是区别开了,不然我不知道从哪里去寻找一个正确答案。(哪怕在IBM的相关网页上都将UCS-2作为UTF-16的别名列出)

    《UTF-16/UCS-2》文中有以下内容:

    UTF-16 is the native internal representation of text in the Microsoft Windows 2000/XP/2003/Vista/CE; Qualcomm BREW operating systems; the Java and .NET bytecode environments; Mac OS X's Cocoa and Core Foundation frameworks; and the Qt cross-platform graphical widget toolkit.[1][2][citation needed]

    Symbian OS used in Nokia S60 handsets and Sony Ericsson UIQ handsets uses UCS-2.

    The Joliet file system, used in CD-ROM media, encodes filenames using UCS-2BE (up to 64 Unicode characters per file).

    Older Windows NT systems (prior to Windows 2000) only support UCS-2.[3]. In Windows XP, no code point above U+FFFF is included in any font delivered with Windows for European languages, possibly with Chinese Windows versions.[clarification needed]

    很明确的说明了Windows 2000以后内核已经是UTF-16的了,这点还真是与平时的感觉相违背,于是可以测试一下。在UTF-16的编码转换函数(Python实现)

    中我在windows下输出了三个太玄经的字符,“”不过实际实在UltraEdit中输出的,虽然在windows下的确是显示出来了,但是也可能是UltraEdit的功能,我们这次用windowsAPI显示出来,以此证明,Windows的内核的确是能够识别并显示此三个太玄经的字符。至于为什么能显示太玄经的字符就表示内核是UTF-16的,是因为UCS-2只能表示到BMP范围的字符,太玄经的字符超出了其能表示的范围,假如你有古老电脑的,安装着Windows NT早期版本的系统,可以用同样的例子试试,应该是不能显示出来的。

    int _tmain(int argc, _TCHAR* argv[])

    {

    wchar_t lwc[8];

    lwc[0] = 0xd834;

    lwc[1] = 0xdf00;

    lwc[2] = 0xd834;

    lwc[3] = 0xdf01;

    lwc[4] = 0xd834;

    lwc[5] = 0xdf02;

    lwc[6] = 0;

    lwc[7] = 0;

    MessageBoxW(NULL, lwc, lwc, MB_OK);

    return 0;

    }

    会弹出一个对话框,显示字符。很显然,Windows内核是能正确识别UTF-16字符了。

    但是为什么平时都说Windows是UCS-2的呢?因为其编程的接口都是UCS-2的,根本不能理解超出UCS-2但是确是UTF-16的字符,比如上述的太玄经字符。在上面的例子中,其实只有3个字符,显示的时候也能正确,但是看下面的例子:

    int _tmain(int argc, _TCHAR* argv[])

    {

    wchar_t lwc[8];

    lwc[0] = 0xd834;

    lwc[1] = 0xdf00;

    lwc[2] = 0xd834;

    lwc[3] = 0xdf01;

    lwc[4] = 0xd834;

    lwc[5] = 0xdf02;

    lwc[6] = 0;

    lwc[7] = 0;

    int i = wcslen(lwc);

    printf("%d\n", i);

    int j = lstrlenW(lwc);

    printf("%d\n", j);

    return 0;

    }

    无论是i,j都是6,也就是说,无论是Windows下的C语言库函数(wcslen),还是其API(lstrlenW是windows的API,这点不要奇怪),都是无法正确识别UTF-16字符的,连数数都不会数,所以实际的编程体验就是,虽然其内核UTF-16化了,但是你还是只能当UCS-2来使用-_-!

    以上测试也许还不能完全让人信服,再看看MFC的例子(VS2005下的MFC版本)

    老地方 http://groups.google.com/group/jiutianfile/

    有一个TestUnicodeMFc.rar的工程,打开看看,就知道了。当太玄经的3个字符在输入框中时,通过CEdit控件计算出来的长度是6,最最与以前多字节的时候想的是,当你删除一个字符(按一下backspace),你删除的不是一个太玄经字符,而是删除了最后一个字符的一半,然后最后一个字符虽然消失了,但是你发现还有其一半的存在,然后计算长度,输出的是5。唯一比以前好的是,没有出现乱码,原因在于,这个单个的UTF-16字符已经超过了UCS-2能表示的范围,所以没有意义。

    至此,我的结论是,Windows是已经从内核支持UTF-16了,但是你还是得在UCS-2上编程-_-!

    关于此部分内容参看《UTF-16/UCS-2》

    关于Unicode的编码范围的内容参看《Mapping of Unicode character planes》

  • 相关阅读:
    cogs.12运输问题2题解
    7.30考试password
    [Lydsy2017年4月月赛]抵制克苏恩题解
    NOIP2015斗地主题解 7.30考试
    「技巧拾珠」线段树维护区间最值
    COGS775 山海经
    POJ2942 Knights of the Round Table
    【学习笔记】二分图
    Luogu3057 (USACO12 FEB) Nearby Cows
    POJ2152 Fire
  • 原文地址:https://www.cnblogs.com/cute/p/1954187.html
Copyright © 2011-2022 走看看