UNICODE 基础知识

 1
UNICODE 基础知识
Unicode.org 是一个国际性的组织,致力于使全球各种语言文字在计算机上使用统一的
编码。经过多年的发展,UNICODE 编码已经发展到了4.1 的版本。
1. 编码范围
早期的UNICODE 版本里,认为UNICODE 应该是一个固定长度的字符集,用一个16
位的整数来表示一个字符,也就是说一个UNICODE 字符占用2 个字节的存储空间。一个
16 位的整数的范围是0~65535,所以早期版本的UNICODE 最多只能支持65535个字符。但
是世界上的文字何其多?单单是汉字就不止6 万个啦。
新版本的UNICODE 为了容纳更多的字符,认为UNICODE 可以是一个可变长度的字符
集。到目前为止,UNICODE 字符集的编码范围为0x000000~0x10FFFF,其码位数量是原来
的17 倍,可以用于表示100 多万个字符。
2. BMP
目前 UNICODE 字符集的编码范围为0x000000~0x10FFFF,可以分为17 个平面,每个
平面占65535个码位。第0 个平面的码位范围是0x0000~0xFFFF,第1 个平面的码位范围是
0x10000~0x1FFFF,依此类推。由于UNICODE 的早期发展中,把世界上大量的常用字符都
放在0x0000~0xFFFF 的码位范围内,所以大量的常用字符都位于第0 个平面里,不在第0
个平面里的字符都是罕见字符。第0 个平面被称为基本平面,也就叫做BMP。
3. UCS-2和UCS-4
UCS-2是很早便有的概念,是指UNICODE 固定长度为2 的双字节字符集,用两个字节
来代表一个字符,后来由于双字节无法表示更多的码位,所以产生了UCS-4。UCS-4 是指
UNICODE 固定长度为4 的四字节字符集,用四个字节来代表一个字符。
UCS-2 最初规定为固定长度为2 字节的字符集,因为UCS-2 无法容纳码位大于或者等
于0x10000 的字符,所以被UTF-16 替代。所有码位大于或等于0x10000 的字符在UCS-2
中都用一个码位为0xFFFD 的字符(该字符不可打印,是表示未知字符的意思)代替。UTF-16
可以完全兼容UCS-2,可以把UCS-2 看作是UTF-16 的一个子集。不建议再使用UCS-2,
建议用UTF-16 替代UCS-2。而UCS-4 与UTF-32 完全等价。具体参考后面的UTF-16 和
UTF-32。
4. big-endian和little-endian
内存总是以一个字节为一个存储单元的,一个16 位的整数0x1234 在内存里如何存储
呢?
在x86的机器里,第1 个内存单元存放0x34,第2个内存单元存放0x12,这类机器是属于
little-endian类型的,就是所谓的低字节在前。
在Power PC的机器里,第1 个内存单元存放0x12,第2 个内存单元存放0x34,这类机器
是属于big-endian类型的,就是所谓的高字节在前。
5. UTF-8、UTF-16和UTF-32
UTF 是指UNICODE 传输格式。UTF-8、UTF-16 和UTF-32 都是UNICODE 的一种表
2
示形式。
(1)UTF-8
UTF-8 是UNICODE 编码的单字节传输格式。UTF-8 可以与ASCII 兼容,所以非常流
行。
UTF-8采用变长编码方式,一个字符可以是1 个字节,也可以是2、3 或4 个字节,编
码范围为0x000000~0x10FFFF。
编码规则如下:
1) 码位范围是0~127 的字符,只占用1 个字节,而且编码与ASCII相同。
2) 码位范围大于127 时,首字节有多少个连续的1,就表示该字符占多少个字节,
首字节的第一个0 之后为部分为实际编码部分,后继字节总是以标志位10 开头,跟在标志
位10 之后的为实际编码部分。
根据上面规则,总结如下:
当要表示的字符的码位范围为0x00~0x7F 的时候就用一个字节:0*******,第一个0
为标志位,剩下的空间正好可以表示ASCII 0-127 的内容。
当要表示的字符的码位范围为0x80~0x7FF的时候就用两个字节:110***** 10******,
第一个字节的110 和第二个字节的10 为标志位。
当要表示的字符的码位范围为0x800~0xFFFF的时候就用三个字节:1110**** 10******
10******,和上面一样,第一个字节的1110和第二、三个字节的10 都是标志位,大部分常
用汉字都在这个区域。
当要表示的字符的码位范围为0x10000~0x10FFFF 的时候就用四个字节:11110****
10****** 10****** 10******,第一个字节的11110 和第二、三、四个字节的10都是标志位。
例如:
一个 UNICODE 字符0xFEFF,其UTF-8 的表示为:EF BB BF。
EF BB BF展开为二进制则是:11101111 10111011 10111111。第一个字节取1111,第
二个字节取111011,第三个字节取111111,合并起来就是11111110 11111111,正好就是
0xFEFF。
(2)UTF-16
UTF-16,一种通俗的叫法,就是直接叫它作UNICODE。虽然UNICODE 可以表示为
UTF-8 或者UTF-32,但是很多时候,人们通常所说的UNICODE 一般就是指UTF-16。
UNICODE 发展到今天,UTF-16 可以完全替代UCS-2。
UTF-16 是UNICODE 编码的双字节传输格式,每一个传输单元是2 个字节。UTF-16
必须区分big-endian和little-endian,由此可见,UTF-16 可以分为UTF-16BE 和UTF-16LE。
UTF-16 采用变长编码方式,一个字符可以是2 个字节,也可以是4 个字节,编码范围
为0x000000~0x10FFFF。
编码规则如下:
1) 码位范围是0x0000~0xFFFF的字符,只占用2 个字节,这个区域就是BMP,世
界上大部分常用字符都在这个区域。
2) 码位范围是0x10000~0x10FFFF 的字符,需要占用4 个字节来表示。BMP中预
留出一个区域,这个区域的码位不表示任何字符,专门作扩展UTF-16 到4 字节使用,这个
区域范围是0xD800~0xDFFF。这个区域叫代理区域,其中0xD800~0xDBFF 这个范围叫高
代理,0xDC00~0xDFFF叫低代理。一般高代理在前,低代理在后,两个代理组成4 字节来
表示一个字符。高代理展开为二进制的110110** ********,其中前面的110110 为标志位。
3
低代理展开为二进制的110111** ********,其中前面的110111 为标志位。高代理取出其低
10 位作为字符编码的高10 位,低代理取出其低10 位作为字符编码的低10位,这样就可以
组成一个20位的数字,这个20位的数字再加上0x10000,所得到的和就是字符的编码,
例如:
在中文里,有一个非常罕见的字符,其编码为0x200B1。UTF-16BE 表示为D8 40 DC
B1,高代理为0xD840,低代理为0xDCB1。高代理展开二进制为11011000 01000000,低代
理展开二进制为11011100 10110001。高代理取出其低10 位00 01000000作为字符编码的高
10 位,低代理取出其低10 位00 10110001 作为字符编码的低10 位,这样就可以组成一个
20 位的数字01 00000000 10110001,就是十六进制的0x100B1,这个数再加上0x10000,得
到的和为0x200B1,这个和就是该字符的UNICODE编码。
(3)UTF-32
UTF-32 是UNICODE 编码的4 字节传输格式,每一个传输单元是4 个字节。UTF-32
是固定长度的编码方式。UTF-32 必须区分big-endian和little-endian,由此可见,UTF-32 可
以分为UTF-32BE 和UTF-32LE。
UTF-32 非常好,任何字符都可以用一个4 字节的编码来表示,固定长度使得处理起来
非常方便,唯一的缺点就是比较浪费空间。
6. BOM
BOM是UNICODE中的一个很重要的概念。什么是BOM?这关系到文本文件的格式。
文本文件,一般以后缀名.txt结尾。所有编程语言的源程序文件,例如*.c、*.cpp、*.h、
*.pas、*.bas、*.java 等等都是文本文件,批处理、Shell 脚本、网页html 和很多配置文件都
是文本文件。在计算机里,文本文件无处不在。
一般的文本文件是采用兼容ANSI 的多字节字符集,在Windows 的记事本里,另存为
的时候选择编码为“ANSI”就是这种类型。不同的国家或地区使用不同的编码,例如简体
中文使用GBK/GB18030 编码,繁体中文使用big-5 编码,日文使用Shift-JIS 编码等等。这
类兼容ANSI的多字节字符集使用非常广泛,但是有个缺点,就是在简体中文的操作系统里,
打开big-5 编码的文本文件会出现乱码,反之也是如此。
使用 UNICODE字符集的文本文件具有通用性,在不同的操作系统打开时,绝对不会出
现乱码的现象(前提是该系统必须安装有对应语言的字体)。使用UNICODE 字符集的文本
文件在比较老的系统,例如Windows 95/98/ME 下面无法显示。
UNICODE 里有个编码为0xFEFF 的字符,该字符是不可显示字符,名为BOM (byte
order mark),主要用于定义字节序,用于区分big-endian和little-endian。一般用于文本文件
的开头。
由于UNICODE 编码的文本文件第一个字符一般都是BOM,一般来说,UTF-16LE 以
FF FE 开头,UTF-16BE 以FE FF开头,UTF-8以EF BB BF开头,UTF-32LE 以FF FE 00 00
开头,UTF-32BE 以00 00 FE FF开头。
7. 在C/C++中使用UNICODE
在Java 语言中,默认的字符类型就是UTF-16。
在C/C++语言中,char 类型是单字节的,char 数组可以保存与ASCII兼容的字符集,包
括ASCII、GBK、GB18030、big-5、UTF-8 等等。
在 C/C++语言中,还有一种字符类型,叫宽字符类型,类型名为wchar_t,可以定义2
字节的(UTF-16)字符。字符或者字符串前要加“L”前缀。例如:
4
wchar_t c = L’a’;
wchar_t pStr[] = L”The quick brown dog jumps over the lazy fox”;
8. UTF-8、UTF-16、UTF-32对照表
名称UTF-8 UTF-16 UTF-16BE UTF-16LE UTF-32 UTF-32BE UTF-32LE
最小代码点0000 0000 0000 0000 0000 0000 0000
最大代码点10FFFF 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF 10FFFF
单元大小8位16位16位16位32位32位32位
字节序N/A BOM BE LE BOM BE LE
单字符最小字节1 2 2 2 4 4 4
单字符最大字节4 4 4 4 4 4 4
BOM表示字节序由BOM决定。
BE 表示字节序为big-endian。
LE 表示字节序为little-endian。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值