您的位置:首页 > 其它

Unicode的定义以及Windows下各个相关名称叫法间的关系

2015-06-04 11:49 405 查看
Unicode的定义

Unicode是为整合全世界的所有语言文字而诞生的。

任何文字(字符)在Unicode中都对应一个值,这个值称为代码点(code point)。代码点的值通常写成如 U+ABCD形式 的格式(不一定是四位,如[b]U+10FFFF)。[/b]

一些人误以为Unicode只是简单的使用16比特的码字,也就是说每一个字符对应 16比特,总共可以表示65536个字符。这是完全不正确的。

在Unicode中,一个字母被映射到一个叫做码点(code point)的东西,这个码点可以看作一个纯粹的逻辑概念。至于码点(code point)如何在内存或磁盘中存储是另外的一个故事了。

码点(code point)的形式:U+0639

U+的意思就是"Unicode",后面跟的数字是十六进制的。

事实上Unicode可以定义的字符数并没有上限,而且现在已经超过65536了。显然,并不是任何Unicode字符都可以用2个字节来表示了。



例如,

1.1从U+0000至U+D7FF以及从U+E000至U+FFFF的码位
1.2 从U+10000到U+10FFFF的码位

1.3从U+D800到U+DFFF的码位

[b]Unicode代码点(code point)就是所谓的[/b]Unicode的编码方式



Unicode的编码方式

Unicode的编码方式与ISO 10646通用字符集(Universal Character
Set,UCS)概念相对应,目前实际应用的Unicode版本对应于UCS-2,使用16的编码空间。也就是每个字符占用2个字节。这样理论上一共最多可以表示216即65536个字符。基本满足各种语言的使用。实际上目前版本的Unicode尚未填充满这16
位编码,保留了大量空间作为特殊使用或将来扩展。

上述16位Unicode字符构成基本多文种平面(Basic Multilingual Plane,简称BMP)。最新(但未实际广泛使用)的Unicode版本定义了16个辅助平面,两者合起来至少需要占据21位的编码空间,比3字节略少。但事实上辅助平面字符仍然占用4字节编码空间,与UCS-4保持一致。未来版本会扩充到ISO
10646-1实现级别3,即涵盖UCS-4的所有字符。UCS-4是一个更大的尚未填充完全的31位字符集,加上恒为0的首位,共需占据32位,即4字节。理论上最多能表示231个字符,完全可以涵盖一切语言所用的符号。

BMP字符的Unicode编码表示为U+hhhh,其中每个h 代表一个十六进制数位。与UCS-2编码完全相同。对应的4字节UCS-4编码后两个字节一致,前两个字节的所有位均为0。

Unicode的实现方式:Unicode Translation Format(UTF)

对应同一个[b]Unicode代码点(code point)(就是所谓的[/b]Unicode的编码方式),可以有不同Unicode的实现方式(即最终存储在变量里的编码值):utf8
utf16 utf32等。
=========================================================================================

UTF16

UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。

不难猜到,UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式直接保存下来。

UTF-16包括三种:UTF-16(即[b]带BOM的utf16,也就是平时我们说UTF-16时具体指的就是这个。[b]带BOM的utf16[/b]就一个字符集,不分为UTF-16(Big
Endian)和UTF-16(Little Endian)
两种字符集,该两者是其在不同字序主机上的实际表现而已),UTF-16BE(Big Endian),UTF-16LE(Little Endian)。[/b]

UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark)的字符来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。

其实BOM是个小聪明的想法。由于UCS-2没有定义(具有代码点为)U+FFFE(的字符,即U+FFFE不在代码点的有效编码空间中),因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF,并且可以判断出是Big Endian还是Little Endian。

举个例子。“ABC”这三个字符用各种方式编码后的结果如下:





Windows(操作系统)平台下默认的Unicode编码为Little Endian的UTF-16(即上述的 FF FE 41 00 42 00 43 00)。你可以打开记事本,写上ABC,然后保存(为Unicode选项),再用二进制编辑器看看它的编码结果。

记事本程序默认编码为ANSI。

注释:

对上图里字符集的分类(最后一行删除不要)



不带BOM的utf16:UTF-16BE和UTF-16LE



带BOM的utf16:UTF-16(Big Endian)和UTF-16(Little Endian)

以下的例子有四个字符:“朱”(U+6731)、半角逗号(U+002C)、“聿”(U+807F)、

(U+2A6A5)。
使用UTF-16编码的例子
编码名称
编码次序
编码
BOM

,




UTF-16LE
小尾序,不含BOM
31 67
2C 00
7F 80
69 D8 A5 DE
UTF-16BE
大尾序,不含BOM
67 31
00 2C
80 7F
D8 69 DE A5
UTF-16LE
小尾序,包含BOM
FF FE
31 67
2C 00
7F 80
69 D8 A5 DE
UTF-16BE
大尾序,包含BOM
FE FF
67 31
00 2C
80 7F
D8 69 DE A5
为了弄清楚UTF-16文件的大小尾序,在UTF-16文件的开首,都会放置一个U+FEFF字符作为Byte
Order Mark(UTF-16LE以FF FE代表,UTF-16BE以FE FF代表),以显示这个文本文件是以UTF-16编码,其中U+FEFF字符在UNICODE中代表的意义是ZERO WIDTH NO-BREAK SPACE,顾名思义,它是个没有宽度也没有断字的空白。

U+FEFF字符是放在一个字符串的开头,或是一个字符的开头,但不会一个字符串里的每个字符前都会放一个U+FEFF字符

-----------------------

在Windows平台下,有一个最简单的转化方法,就是使用内置的记事本小程序Notepad.exe。打开文件后,点击"文件"菜单中的"另存为"命令,会跳出一个对话框,在最底部有一个"编码"的下拉条。





里面有四个选项:ANSI,Unicode,Unicode big endian 和 UTF-8。

1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。

2)Unicode编码指的是UCS-2编码方式UTF-16(Big[b] Endian)[/b]【更确切地说,是UCS-2编码方式】,即直接用两个字节存入字符的Unicode码。这个选项用的little endian格式。

3)Unicode big endian编码与上一个选项相对应。我在下一节会解释little endian和big endian的涵义。

4)UTF-8编码,也就是上一节谈到的编码方法。

选择完"编码方式"后,点击"保存"按钮,文件的编码方式就立刻转换好了。

==========================

UTF-16Unicode字符编码五层次模型的第三层:字符编码表(Character Encoding Form,也称为"storage
format")的一种实现方式。即把Unicode字符集的抽象码位映射为16位长的整数(即码元)的序列,用于数据存储或传递。Unicode字符的码位,需要1个或者2个16位长的码元来表示,因此这是一个变长表示。
UTF是"Unicode/UCSTransformation Format"的首字母缩写,即把Unicode字符转换为某种格式之意。UTF-16正式定义于ISO/IEC 10646-1的附录C,而RFC2781也定义了相似的做法。

UTF-16描述
Unicode的编码空间从U+0000到U+10FFFF,共有1,112,064个码位(code point)可用来映射字符. Unicode的编码空间可以划分为17个平面(plane),每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000到U+xxFFFF,其中xx表示十六进制值从0016到1016,共计17个平面。第一个平面称为基本多语言平面(BasicMultilingual
Plane, BMP),或称第零平面(Plane 0)。其他平面称为辅助平面(Supplementary Planes)。基本多语言平面内,从U+D800到U+DFFF之间的码位区段是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码。

UTF-16与UCS-2的关系
UTF-16可看成是UCS-2的父集。在没有辅助平面字符(surrogate
code points)前,UTF-16与UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支持UCS-2编码,那其实是暗指它不能支持在UTF-16中超过2bytes的字集。对于小于0x10000的UCS码,UTF-16编码就等于UCS码。

Microsoft Windows操作系统内核对Unicode的支持
Windows操作系统内核中的字符表示为UTF-16小尾序,可以正确处理、显示以4字节存储的字符。但是Windows API实际上仅能正确处理UCS-2字符,即仅以2字节存储的,码位小于U+FFFF的Unicode字符。其根源是Windows
API只用UCS-2字符集文件来解释[b]wchar_t数据类型
的变量。[/b]Microsoft C++语言把wchar_t数据类型定义为16比特的unsigned short,这就与一个wchar_t型变量对应一个宽字符,(与)可以存储一个Unicode字符的规定相矛盾。相反,Linux平台的GCC编译器规定一个wchar_t是4字节长度,可以存储一个UTF-32字符,宁可浪费了很大的存储空间。下例运行于Windows平台的C++程序可说明此点:

// 此源文件在Windows平台上必须保存为Unicode格式(即UTF-16小尾)
// 因为包含的汉字

(U+2A6A5)
,不能在简体中文版Windows默认的代码页936(即GBK)中表示。
// 该汉字在UTF-16小尾序中用4个字节表示,
// Windows操作系统能正确显示这样的在UTF-16需用4字节表示的字符
// 但是Windows API不能正确处理这样的在UTF-16需用4字节表示的字符,把它判定为2个UCS-2字符

#include <windows.h>
int main()
{
constwchar_t lwc[]=L

;

MessageBoxW(NULL,lwc, lwc, MB_OK);

inti = wcslen(lwc);
printf("%d\n",i);
intj = lstrlenW(lwc);
printf("%d\n",j);

return0;
}

附加:

在MS的IDE中我们可以看到这样一个选项





这里的Unicode一般就是指的UTF16LE(更确切地说是,UCS-2字符集),双字节宽字符,也就是wchar_t。

小结:VS 2010等MS的开发工具里说的Unicode一般就是指的UTF16LE(更确切地说是,对应UCS-2字符集代码点),而MS的记事本程序里说的Unicode一般就是指的UTF-16(Big[b] Endian)[/b]【即带有BOM的,更确切地说,是对应带有BOM的UCS-2代码点】

参考:

字符编码问题,UNICODE\UTF-8\UTF-16\UTF-32\UCS\ANSI\GBK\GB2312等乱七八糟的名词

字符编码笔记:ASCII,Unicode和UTF-8

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: