宁波.Net技术讨论区

浅谈文字编码和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编码需要两个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-0x10FFFF。《谈谈Unicode编码》主要介绍了BMP的编码,本文将介绍完整的Unicode编码,并从多个角度浏览Unicode。本文的介绍基于Unicode 5.0.0版本。

4.1 浏览Unicode

先看一些数字:每个平面有2^16=65536个码位。Unicode计划使用了17个平面,一共有17*65536=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-65534*2-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 Block

UCD中的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
D7AF
Hangul Syllables
朝鲜文音节

D800
DB7F
High Surrogates
高位替代

DB80
DBFF
High Private Use Surrogates
高位专用替代

DC00
DFFF
Low Surrogates
低位替代

E000
F8FF
Private Use Area
专用区

F900
FAFF
CJK Compatibility Ideographs
中日韩兼容表意文字

FB00
FB4F
Alphabetic Presentation Forms
字母变体显现形式

FB50
FDFF
Arabic Presentation Forms-A
阿拉伯文变体显现形式-A

FE00
FE0F
Variation Selectors
字型变换选取器

FE10
FE1F
Vertical Forms
竖排标点符号

FE20
FE2F
Combining Half Marks
组合半角标示

FE30
FE4F
CJK Compatibility Forms
中日韩兼容形式

FE50
FE6F
Small Form Variants
小型变体形式

FE70
FEFF
Arabic Presentation Forms-B
阿拉伯文变体显现形式-B

FF00
FFEF
Halfwidth and Fullwidth Forms
半角及全角字符

FFF0
FFFF
Specials
特殊区域

10000
1007F
Linear B Syllabary
线形文字B音节文字

10080
100FF
Linear B Ideograms
线形文字B表意文字

10100
1013F
Aegean Numbers
爱琴海数字

10140
1018F
Ancient Greek Numbers
古希腊数字

10300
1032F
Old Italic
古意大利文

10330
1034F
Gothic
哥特文

10380
1039F
Ugaritic
乌加里特楔形文字

103A0
103DF
Old Persian
古波斯文

10400
1044F
Deseret
德塞雷特大学音标

10450
1047F
Shavian
肃伯纳速记符号

10480
104AF
Osmanya
Osmanya字母表

10800
1083F
Cypriot Syllabary
塞浦路斯音节文字

10900
1091F
Phoenician
腓尼基文

10A00
10A5F
Kharoshthi
迦娄士悌文

12000
123FF
Cuneiform
楔形文字

12400
1247F
Cuneiform Numbers and Punctuation
楔形文字数字和标点

1D000
1D0FF
Byzantine Musical Symbols
东正教音乐符号

1D100
1D1FF
Musical Symbols
音乐符号

1D200
1D24F
Ancient Greek Musical Notation
古希腊音乐符号

1D300
1D35F
Tai Xuan Jing Symbols
太玄经符号

1D360
1D37F
Counting Rod Numerals
算筹

1D400
1D7FF
Mathematical Alphanumeric Symbols
数学用字母数字符号

20000
2A6DF
CJK Unified Ideographs Extension B
中日韩统一表意文字扩充 B

2F800
2FA1F
CJK Compatibility Ideographs Supplement
中日韩兼容表意文字补充

E0000
E007F
Tags
标签

E0100
E01EF
Variation Selectors Supplement
字型变换选取器补充

F0000
FFFFF
Supplementary Private Use Area-A
补充专用区-A

100000
10FFFF
Supplementary Private Use Area-B
补充专用区-B

Block是Unicode字符的一个属性。属于同一个Block的字符有着相近的用途。Block表中的开始码位、结束码位只是用来划分出一块区域,在开始码位和结束码位之间可能还有很多未定义的码位。使用UniToy,大家可以按照Block浏览Unicode字符,既可以按列表显示:

block_list

也可以显示每个字符的详细信息:

block_detail

posted @ 2011-01-20 10:18  山 人  阅读(873)  评论(0编辑  收藏  举报