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文件的大小尾序,在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-16是Unicode字符编码五层次模型的第三层:字符编码表(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是为整合全世界的所有语言文字而诞生的。
任何文字(字符)在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 |
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-16是Unicode字符编码五层次模型的第三层:字符编码表(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
相关文章推荐
- ODROID-X2 SD card install Arch linux
- iOS学习笔记——iOS国际化
- linux: 获取系统资源(getconf(1), sysconf(3))
- Infragistics用户界面组件宣布推出infragistics Ultimate更新15.1版本。
- 网络定位服务NetworkLocationProvider
- 怎样在多线程中使用JNI?
- win8和win8.1动态绑定数据到ListView
- SUDO的有关知识总结
- android studio 如何导入eclipse工程
- Ubuntu 14.04安装语言包后无法选择汉语问题解决
- Android底层开发(二)之JNI层 第三步
- LIB和DLL的区别与使用
- iOS学习笔记——获取手机信息(UIDevice、NSBundle、NSLocale)
- ArcGIS Engine中正确释放打开资源<转>
- [转]五种常见的 PHP 设计模式
- mac eclipse 修改SDK路径
- 添加产品唯一性限制以后,复制按钮不能使用
- UITextField
- 在 Mockplus 设置页面链接,实现页面交互
- OLEDB错误