正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。
可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是 Unicode
,就像它的名字都表示的,这是一种所有符号的编码。
Unicode 当然是一个很大的集合,现在的规模可以容纳 100 多万个符号。每个符号的编码都不一样,比如,U+0639
表示阿拉伯字母 Ain
,U+0041
表示英语的大写字母 A
,U+4E25
表示汉字严。具体的符号对应表,可以查询 unicode.org,或者专门的汉字对应表。
1. Unicode 历史
九十年代左右有两个组织分别做了两个码表要做统一, ISO (国际标准化组织, International Organization for Standardization)的 UCS 10646(通用字符集, Universal Character Set)和统一码联盟(Unicode Consortium)的Unicode. 但我们不需要两个不兼容的统一字符集, 在1991年前后, 他们终于联合起来共同维护一个标准了(他们还是各自发展, 但字符集统一), 从 Unicode2.0
开始,采用与 ISO10646-1
相同的字库和字码。两者目前兼容发展着。
2. 范围
UCS
和 Unicode
使用最大 32 bit
来表示字符, 可以表示 42 亿个字符(4,294,967,296), 目前只使用了 1,114,112 个码位, 从 0x0~0x10FFFF
. 它们为了和不同的区域性字符集相互兼容, 把其首 256 字符使用 ISO8859-1
所定义的字符, 并把大量字符重复编到不同的字符码位置, 从而使得旧有的纷繁复杂的编码方式得以和Unicode编码直接互相转换, 而不会丢失任何信息。
摘抄自其它资料, 这点我存疑: 事实上我发现它只向下兼容
8859-1
, 并且只有使用UTF-8
转换格式时才行, 直接使用Unicode==UTF-16
还是错误结果. 错误原因在下边UTF
那有描述.
3. 编码方式
3.1 USF-4 / UCF-2
UCS-4
为 4 字节, 它根据最高位为 0 的最高那 1 个字节, 表示出 2 的 7 次方 128 个 group
; 然后每个 group
根据此高字节分为 256 个plane
; 每个 plane
根据根据第 3 个字节分为 256 个 row
; 每 row
有 256 个 cell
.
group 0
的 plane 0
称为 基本多文种平面, BMP (Basic Multilingual Plane).
如果 UCS-4
的前 2 个字节全零(也就是用了 group 0 plane 0
),那么将 UCS-4
的 BMP 去掉前两个 0 字节就得到了 UCS-2
.
128 group 256 plane 256 row 256 cell
0000 0000,0000 0000,0000 0000,0000 0000
3.2 plane 的使用
Unicode
计划使用 17 个平面, 一共有 1765535=*1,114,112 个码位. 在 Unicode5.0
中, 已定义的码位只有 238,605 个, 分布在plane0,1,2,14,15,16
中:
plane 15,16
只是定义了 65534 个码位专用区(Private Use Area, PUA), 分别是0xF0000~0xFFFFD
和0x100000~0x10FFFD
. 专用区 PUA: 留给大家放自定义字符的区域.plane 0
也有一个专用区:0xE000~0xF8FF
, 共 6400 个码位. 它还有代理区(Surrogate)0xD800~0xDFFF
(55296~57343), 共 2048 个码位. 代理区的目的是: 用两个 UTF-16 字符表示 BMP 之外的字符.- 238605-65535*2-6400-2048=99,089. 这 9 万多个字符定义在
plane 0
(52080),plane 1
(3419),plane2
(43253),plane 14
(337)上. 有 71,226 个汉字,plane 2
的 43253 都是汉字,plane 0
上定义了 27973 个汉字.
Unicode 3.1
开始使用辅助 plane
, 2015年6月17号 Unicode 8.0
发布: Unicode Version 8.0 Released (2015.06.17).
3.3 Unicode 码表区段
目前的 Unicode
码表区段:
0000..007F; Basic Latin
0080..00FF; Latin-1 Supplement
0100..017F; Latin Extended-A
0180..024F; Latin Extended-B
0250..02AF; IPA Extensions
02B0..02FF; Spacing Modifier Letters
0300..036F; Combining Diacritical Marks
0370..03FF; Greek
0400..04FF; Cyrillic
0530..058F; Armenian
0590..05FF; Hebrew
0600..06FF; Arabic
0700..074F; Syriac
0780..07BF; Thaana
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
13A0..13FF; Cherokee
1400..167F; Unified Canadian Aboriginal Syllabics
1680..169F; Ogham
16A0..16FF; Runic
1780..17FF; Khmer
1800..18AF; Mongolian
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 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
2800..28FF; Braille Patterns
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
3200..32FF; Enclosed CJK Letters and Months
3300..33FF; CJK Compatibility
3400..4DB5; CJK Unified Ideographs Extension A
4E00..9FFF; CJK Unified Ideographs
A000..A48F; Yi Syllables
A490..A4CF; Yi Radicals
AC00..D7A3; Hangul Syllables
D800..DB7F; High Surrogates
DB80..DBFF; High Private Use Surrogates
DC00..DFFF; Low Surrogates
E000..F8FF; Private Use
F900..FAFF; CJK Compatibility Ideographs
FB00..FB4F; Alphabetic Presentation Forms
FB50..FDFF; Arabic Presentation Forms-A
FE20..FE2F; Combining Half Marks
FE30..FE4F; CJK Compatibility Forms
FE50..FE6F; Small Form Variants
FE70..FEFE; Arabic Presentation Forms-B
FEFF..FEFF; Specials
FF00..FFEF; Halfwidth and Fullwidth Forms
FFF0..FFFD; Specials
10300..1032F; Old Italic 10330..1034F; Gothic
10400..1044F; Deseret
1D000..1D0FF; Byzantine Musical Symbols
1D100..1D1FF; Musical Symbols
1D400..1D7FF; Mathematical Alphanumeric Symbols
20000..2A6D6; CJK Unified Ideographs Extension B
2F800..2FA1F; CJK Compatibility Ideographs Supplement
E0000..E007F; Tags
F0000..FFFFD; Private Use
100000..10FFFD; Private Use
3.4 CJK
最常用的 CJK(Chinese Japanese Korean 中日韩文)区间段是 4E00~9FFF
, 但 9FA6~9FFF
还是空的, 所以实际有值得是 4E00~9FA5
, 这也是大部分人判断中文所用的区段. 但大家要知道,其实 CJK 大部分是描述的中文,日文和韩文还有相应的区间. 上表中带有 CJK 的、平假名Hiragana、片假名Katakana、朝鲜文Hangul的都是中日韩文可能的字符区间: CJK Unified Ideographs
.
只是常用的区间, 全部 CJK 区间应该是:
2E80..2EFF(11904-12031): CJK Radicals Supplement
3000..303F(12288-12351): CJK Symbols and Punctuation
3040..309F(12352-12447): Hiragana(日文平假名)
30A0..30FF(12448-12543): Katakana(日文片假名)
3130..318F(12592-12687): Hangul Compatibility Jamo(朝鲜文兼容字母)
31F0..31FF(12784-12799): Katakana Phonetic Extensions(日文片假名语音括展)
3200..32FF(12800-13055): Enclosed CJK Letters and Months
3300..33FF(13056-13311): CJK Compatibility
3400..4DB5(13312-19893): CJK Unified Ideographs Extension A
4E00..9FFF(19968-40959): CJK Unified Ideographs
AC00..D7AF(44032-55215): Hangul Syllables(朝鲜文音节)
F900..FAFF(63744-64255): CJK Compatibility Ideographs
FE30..FE4F(65072-65103): CJK Compatibility Forms
20000..2A6D6(131072-173782): CJK Unified Ideographs Extension B
2F800..2FA1F(194560-195103): CJK Compatibility Ideographs Supplement
4. Unicode 的问题
需要注意的是, Unicode
只是一个符号集, 它只规定了符号的二进制代码, 却没有规定这个二进制代码应该如何存储.
比如, 汉字 严
的 Unicode
是十六进制数 4E25
, 转换成二进制数足足有 15 位(100111000100101
), 也就是说这个符号的表示至少需要 2 个字节. 表示其他更大的符号, 可能需要 3 个字节或者 4 个字节, 甚至更多.
这里就有两个严重的问题:
- 如何才能区别
Unicode
和ASCII
? 计算机怎么知道三个字节表示一个符号, 而不是分别表示三个ASCII
符号呢? - 第二个问题是, 我们已经知道, 英文字母只用一个字节表示就够了, 如果
Unicode
统一规定, 每个符号用三个或四个字节表示, 那么每个英文字母前都必然有二到三个字节是0
, 这对于存储来说是极大的浪费, 文本文件的大小会因此大出二三倍, 这是无法接受的.
它们造成的结果是:
- 出现了
Unicode
的多种存储方式, 也就是说有许多种不同的二进制格式, 可以用来表示Unicode
. Unicode
在很长一段时间内无法推广, 直到互联网的出现.
互联网的普及, 强烈要求出现一种统一的编码方式. UTF-8
就是在互联网上使用最广的一种 Unicode
的实现方式. 其他实现方式还包括 UTF-16
(字符用两个字节或四个字节表示) 和 UTF-32
(字符用四个字节表示), 不过在互联网上基本不用. 重复一遍, 这里的关系是, UTF-8
是 Unicode
的实现方式之一.
5. Unicode/UCS 总结
Unicode/UCS总结: 也就是说它用 2~4 个字节的空间描述了已知的接近全部的字符 (并且仍在更新,还会把笑脸之类的字符也放入其中), 而通常使用的 plane 0
也就是 UCS-2
, 使用 2 个字节描述了比较常用的字符, 包括大量的 CJK 文字, 所以大家平常能用到的字符大体都在 UCS-2 中包括了.