浅谈文字编码和Unicode(下)
3 字符编码模型
程序员经常会面对复杂的问题,而降低复杂性的最简单的方法就是分而治之。Peter Constable在他的文章"Character set encoding basics Understanding character set encodings and legacy encodings"中描述了字符编码的四层模型。我觉得这种说法确实可以更清晰地展现字符编码中发生的事情,所以在这里也介绍一下。
3.1 字符的范围(Abstract character repertoire)
设计字符编码的第一层就是确定字符的范围,即要支持哪些字符。有些编码方案的字符范围是固定的,例如ASCII、ISO 8859 系列。有些编码方案的字符范围是开放的,例如Unicode的字符范围就是世界上所有的字符。
3.2 用数字表示字符(Coded character set)
设计字符编码的第二层是将字符和数字对应起来。可以将这个层次理解成数学家(即从数学角度)看到的字符编码。数学家看到的字符编码是一个正整数。例如在Unicode中:汉字“字”对应的数字是23383。汉字“”对应的数字是134192。
在写html文件时,可以通过输入"字"来插入字符“字”。不过在设计字符编码时,我们还是习惯用16进制表示数字。即将23383写成0x5BD7,将134192写成0x20C30。
3.3 用基本数据类型表示字符(Character encoding form)
设计字符编码的第三层是用编程语言中的基本数据类型来表示字符。可以将这个层次理解成程序员看到的字符编码。在Unicode中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写,可以翻译成Unicode字符集转换格式,即怎样将Unicode定义的数字转换成程序数据。例如,“汉字”对应的数字是0x6c49和0x5b57,而编码的程序数据是:
BYTE data_utf8【】={0xE6,0xB1,0x89,0xE5,0xAD,0x97}; // UTF-8编码
WORD data_utf16【】={0x6c49,0x5b57}; // UTF-16编码
DWORD data_utf32【】={0x6c49,0x5b57}; // UTF-32编码
这里用BYTE、WORD、DWORD分别表示无符号8位整数,无符号16位整数和无符号32位整数。UTF-8、UTF-16、UTF-32分别以BYTE、WORD、DWORD作为编码单位。
“汉字”的UTF-8编码需要6个字节。“汉字”的UTF-16编码需要两个WORD,大小是4个字节。“汉字”的UTF-32编码需要两个//代码效果参考:http://www.zidongmutanji.com/zsjx/524915.html
DWORD,大小是8个字节。4.2节会介绍将数字映射到UTF编码的规则。3.4 作为字节流的字符(Character encoding scheme)
字符编码的第四层是计算机看到的字符,即在文件或内存中的字节流。例如,“字”的UTF-32编码是0x5b57,如果用little endian表示,字节流是“57 5b 00 00”。如果用big endian表示,字节流是“00 00 5b 57”。
字符编码的第三层规定了一个字符由哪些编码单位按什么顺序表示。字符编码的第四层在第三层的基础上又考虑了编码单位内部的字节序。UTF-8的编码单位是字节,不受字节序的影响。UTF-16、UTF-32根据字节序的不同,又衍生出UTF-16LE、UTF-16BE、UTF-32LE、UTF-32BE四种编码方案。LE和BE分别是Little Endian和Big Endian的缩写。
3.5 小结
通过四层模型,我们又把字符编码中发生的这些事情梳理了一遍。其实大多数代码页都不需要完整的四层模型,例如GB18030以字节为编码单位,直接规定了字节序列和字符的映射关系,跳过了第二层,也不需要第四层。
4 再谈Unicode
Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。
Unicode字符集可以简写为UCS(Unicode Character Set)。早期的Unicode标准有UCS-2、UCS-4的说法。UCS-2用两个字节编码,UCS-4用4个字节编码。UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个平面(plane)。每个平面根据第3个字节分为256行 (row),每行有256个码位(cell)。group 0的平面0被称作BMP(Basic Multilingual Plane)。将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。
Unicode标准计划使用group 0 的17个平面: 从BMP(平面0)到平面16,即数字0-0//代码效果参考:http://www.zidongmutanji.com/bxxx/523598.html
x10FFFF。《谈谈Unicode编码》主要介绍了BMP的编码,本文将介绍完整的Unicode编码,并从多个角度浏览Unicode。本文的介绍基于Unicode 5.0.0版本。4.1 浏览Unicode
先看一些数字:每个平面有2^16=65536个码位。Unicode计划使用了17个平面,一共有1765536=1114112个码位。其实,现在已定义的码位只有238605个,分布在平面0、平面1、平面2、平面14、平面15、平面16。其中平面15和平面16上只是定义了两个各占65534个码位的专用区(Private Use Area),分别是0xF0000-0xFFFFD和0x100000-0x10FFFD。所谓专用区,就是保留给大家放自定义字符的区域,可以简写为PUA。
平面0也有一个专用区:0xE000-0xF8FF,有6400个码位。平面0的0xD800-0xDFFF,共2048个码位,是一个被称作代理区(Surrogate)的特殊区域。它的用途将在4.2节介绍。
238605-655342-6400-2408=99089。余下的99089个已定义码位分布在平面0、平面1、平面2和平面14上,它们对应着Unicode目前定义的99089个字符,其中包括71226个汉字。平面0、平面1、平面2和平面14上分别定义了52080、3419、43253和337个字符。平面2的43253个字符都是汉字。平面0上定义了27973个汉字。
在更深入地了解Unicode字符前,我们先了解一下UCD。
4.1.1 什么是UCD
UCD是Unicode字符数据库(Unicode Character Database)的缩写。UCD由一些描述Unicode字符属性和内部关系的纯文本或html文件组成。大家可以在Unicode组织的网站看到UCD的最新版本。
UCD中的文本文件大都是适合于程序分析的Unicode相关数据。其中的html文件解释了数据库的组织,数据的格式和含义。UCD中最庞大的文件无疑就是描述汉字属性的文件Unihan.txt。在UCD 5.0,0中,Unihan.txt文件大小有28,221K字节。Unihan.txt中包含了很多有参考价值的索引,例如汉字部首、笔划、拼音、使用频度、四角号码排序等。这些索引都是基于一些比较权威的辞典,但大多数索引只能检索部分汉字。
我介绍UCD的目的主要是为了使用其中的两个概念:Block和Script。
4.1.2 //代码效果参考:http://www.zidongmutanji.com/bxxx/111448.html
BlockUCD中的Blocks.txt将Unicode的码位分割成一些连续的Block,并描述了每个Block的用途:
开始码位
结束码位
Block名称(英文)
Block名称(中文)
0000
007F
Basic Latin
基本拉丁字母
0080
00FF
Latin-1 Supplement
拉丁字母补充-1
0100
017F
Latin Extended-A
拉丁字母扩充-A
0180
024F
Latin Extended-B
拉丁字母扩充-B
0250
02AF
IPA Extensions
国际音标扩充
02B0
02FF
Spacing Modifier Letters
进格修饰字符
0300
036F
Combining Diacritical Marks
组合附加符号
0370
03FF
Greek and Coptic
希腊文和哥普特文
0400
04FF
Cyrillic
西里尔文
0500
052F
Cyrillic Supplement
西里尔文补充
0530
058F
Armenian
亚美尼亚文
0590
05FF
Hebrew
希伯来文
0600
06FF
Arabic
基本阿拉伯文
0700
074F
Syriac
叙利亚文
0750
077F
Arabic Supplement
阿拉伯文补充
0780
07BF
Thaana
塔纳文
07C0
07FF
NKo
N'Ko字母表
0900
097F
Devanagari
天成文书(梵文)
0980
09FF
Bengali
孟加拉文
0A00
0A7F
Gurmukhi
锡克教文
0A80
0AFF
Gujarati
古吉拉特文
0B00
0B7F
Oriya
奥里亚文
0B80
0BFF
Tamil
泰米尔文
0C00
0C7F
Telugu
泰卢固文
0C80
0CFF
Kannada
卡纳达文
0D00
0D7F
Malayalam
德拉维族文
0D80
0DFF
Sinhala
僧伽罗文
0E00
0E7F
Thai
泰文
0E80
0EFF
Lao
老挝文
0F00
0FFF
Tibetan
藏文
1000
109F
Myanmar
缅甸文
10A0
10FF
Georgian
格鲁吉亚文
1100
11FF
Hangul Jamo
朝鲜文
1200
137F
Ethiopic
埃塞俄比亚文
1380
139F
Ethiopic Supplement
埃塞俄比亚文补充
13A0
13FF
Cherokee
切罗基文
1400
167F
Unified Canadian Aboriginal Syllabics
加拿大印第安方言
1680
169F
Ogham
欧甘文
16A0
16FF
Runic
北欧古字
1700
171F
Tagalog
塔加路文
1720
173F
Hanunoo
哈努诺文
1740
175F
Buhid
布迪文
1760
177F
Tagbanwa
Tagbanwa文
1780
17FF
Khmer
高棉文
1800
18AF
Mongolian
蒙古文
1900
194F
Limbu
林布文
1950
197F
Tai Le
德宏傣文
1980
19DF
New Tai Lue
新傣文
19E0
19FF
Khmer Symbols
高棉文
1A00
1A1F
Buginese
布吉文
1B00
1B7F
Balinese
巴厘文
1D00
1D7F
Phonetic Extensions
拉丁字母音标扩充
1D80
1DBF
Phonetic Extensions Supplement
拉丁字母音标扩充增补
1DC0
1DFF
Combining Diacritical Marks Supplement
组合附加符号补充
1E00
1EFF
Latin Extended Additional
拉丁字母扩充附加
1F00
1FFF
Greek Extended
希腊文扩充
2000
206F
General Punctuation
一般标点符号
2070
209F
Superscripts and Subscripts
上标和下标
20A0
20CF
Currency Symbols
货币符号
20D0
20FF
Combining Diacritical Marks for Symbols
符号用组合附加符号
2100
214F
Letterlike Symbols
似字母符号
2150
218F
Number Forms
数字形式
2190
21FF
Arrows
箭头符号
2200
22FF
Mathematical Operators
数学运算符号
2300
23FF
Miscellaneous Technical
零杂技术用符号
2400
243F
Control Pictures
控制图符
2440
245F
Optical Character Recognition
光学字符识别
2460
24FF
Enclosed Alphanumerics
带括号的字母数字
2500
257F
Box Drawing
制表符
2580
259F
Block Elements
方块元素
25A0
25FF
Geometric Shapes
几何形状
2600
26FF
Miscellaneous Symbols
零杂符号
2700
27BF
Dingbats
杂锦字型
27C0
27EF
Miscellaneous Mathematical Symbols-A
零杂数学符号-A
27F0
27FF
Supplemental Arrows-A
箭头符号补充-A
2800
28FF
Braille Patterns
盲文
2900
297F
Supplemental Arrows-B
箭头符号补充-B
2980
29FF
Miscellaneous Mathematical Symbols-B
零杂数学符号-B
2A00
2AFF
Supplemental Mathematical Operators
数学运算符号
2B00
2BFF
Miscellaneous Symbols and Arrows
零杂符号和箭头
2C00
2C5F
Glagolitic
格拉哥里字母表
2C60
2C7F
Latin Extended-C
拉丁字母扩充-C
2C80
2CFF
Coptic
科普特文
2D00
2D2F
Georgian Supplement
格鲁吉亚文补充
2D30
2D7F
Tifinagh
提非纳字母
2D80
2DDF
Ethiopic Extended
埃塞俄比亚文扩充
2E00
2E7F
Supplemental Punctuation
标点符号补充
2E80
2EFF
CJK Radicals Supplement
中日韩部首补充
2F00
2FDF
Kangxi Radicals
康熙字典部首
2FF0
2FFF
Ideographic Description Characters
汉字结构描述字符
3000
303F
CJK Symbols and Punctuation
中日韩符号和标点
3040
309F
Hiragana
平假名
30A0
30FF
Katakana
片假名
3100
312F
Bopomofo
注音符号
3130
318F
Hangul Compatibility Jamo
朝鲜文兼容字母
3190
319F
Kanbun
日文的汉字批注
31A0
31BF
Bopomofo Extended
注音符号扩充
31C0
31EF
CJK Strokes
中日韩笔划
31F0
31FF
Katakana Phonetic Extensions
片假名音标扩充
3200
32FF
Enclosed CJK Letters and Months
带括号的中日韩字母及月份
3300
33FF
CJK Compatibility
中日韩兼容字符
3400
4DBF
CJK Unified Ideographs Extension A
中日韩统一表意文字扩充A
4DC0
4DFF
Yijing Hexagram Symbols
易经六十四卦象
4E00
9FFF
CJK Unified Ideographs
中日韩统一表意文字
A000
A48F
Yi Syllables
彝文音节
A490
A4CF
Yi Radicals
彝文字根
A700
A71F
Modifier Tone Letters
声调修饰字母
A720
A7FF
Latin Extended-D
拉丁字母扩充-D
A800
A82F
Syloti Nagri
Syloti Nagri字母表
A840
A87F
Phags-pa
Phags-pa字母表
AC00<