正如上一节所说,世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。为什么电子邮件常常出现乱码?就是因为发信人和收信人使用的编码方式不一样。

可以想象,如果有一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,那么乱码问题就会消失。这就是 Unicode,就像它的名字都表示的,这是一种所有符号的编码。

Unicode 当然是一个很大的集合,现在的规模可以容纳 100 多万个符号。每个符号的编码都不一样,比如,U+0639 表示阿拉伯字母 AinU+0041 表示英语的大写字母 AU+4E25 表示汉字严。具体的符号对应表,可以查询 unicode.org,或者专门的汉字对应表

1. Unicode 历史

九十年代左右有两个组织分别做了两个码表要做统一, ISO (国际标准化组织, International Organization for Standardization)的 UCS 10646(通用字符集, Universal Character Set)和统一码联盟(Unicode Consortium)的Unicode. 但我们不需要两个不兼容的统一字符集, 在1991年前后, 他们终于联合起来共同维护一个标准了(他们还是各自发展, 但字符集统一), 从 Unicode2.0 开始,采用与 ISO10646-1相同的字库和字码。两者目前兼容发展着。

2. 范围

UCSUnicode 使用最大 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 0plane 0 称为 基本多文种平面, BMP (Basic Multilingual Plane).

如果 UCS-4 的前 2 个字节全零(也就是用了 group 0 plane 0),那么将 UCS-4 的 BMP 去掉前两个 0 字节就得到了 UCS-2.

  1. 128 group 256 plane 256 row 256 cell
  2. 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~0xFFFFD0x100000~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 个字节, 甚至更多.

这里就有两个严重的问题:

  1. 如何才能区别 UnicodeASCII? 计算机怎么知道三个字节表示一个符号, 而不是分别表示三个 ASCII 符号呢?
  2. 第二个问题是, 我们已经知道, 英文字母只用一个字节表示就够了, 如果 Unicode 统一规定, 每个符号用三个或四个字节表示, 那么每个英文字母前都必然有二到三个字节是 0, 这对于存储来说是极大的浪费, 文本文件的大小会因此大出二三倍, 这是无法接受的.

它们造成的结果是:

  1. 出现了 Unicode多种存储方式, 也就是说有许多种不同的二进制格式, 可以用来表示 Unicode.
  2. Unicode 在很长一段时间内无法推广, 直到互联网的出现.

互联网的普及, 强烈要求出现一种统一的编码方式. UTF-8 就是在互联网上使用最广的一种 Unicode 的实现方式. 其他实现方式还包括 UTF-16(字符用两个字节或四个字节表示) 和 UTF-32(字符用四个字节表示), 不过在互联网上基本不用. 重复一遍, 这里的关系是, UTF-8Unicode实现方式之一.

5. Unicode/UCS 总结

Unicode/UCS总结: 也就是说它用 2~4 个字节的空间描述了已知的接近全部的字符 (并且仍在更新,还会把笑脸之类的字符也放入其中), 而通常使用的 plane 0 也就是 UCS-2, 使用 2 个字节描述了比较常用的字符, 包括大量的 CJK 文字, 所以大家平常能用到的字符大体都在 UCS-2 中包括了.

6. References

[1] Java中char和String 的深入理解 - 字符编码1