简介[ | ]
统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。
统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
发展历程[ | ]
1990年开始研发,1994年正式发布1.0版本,2022年9月13日发布15.0版本。
统一码简介[ | ]
如果把各种文字编码形容为各地的方言,那么统一码就是世界各国合作开发的一种语言。
在这种语言环境下,不会再有语言的编码冲突,在同屏下,可以显示任何语言的内容,这就是统一码的最大好处。就是将世界上所有的文字用2个字节统一进行编码。那样,像这样统一编码,2个字节就已经足够容纳世界上所有语言的大部分文字了。
Universal Multiple-Octet Coded Character Set,简称为UCS。
现在用的是UCS-2,即2个字节编码,而UCS-4是为了防止将来2个字节不够用才开发的。
统一码是一种在计算机上使用的字符编码,1990年开始研发,1994年正式公布。随着计算机工作能力的增强,统一码也在面世以来的十多年里得到普及。
统一码是基于通用字符集(Universal Character Set)的标准来发展,同时也以出版物的形式(The 统一码 Standard,目前第五版由Addison-Wesley Professional出版,ISBN-10: 0321480910)对外发表。
2005年3月31日推出4.1.0版本。
2022年9月13日推出15.0版本。
编码和实现[ | ]
大概来说,统一码编码系统可分为编码方式和实现方式两个层次。
编码方式[ | ]
统一码是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。统一码用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。
统一码字符集可以简写为UCS(统一码Character Set)。早期的统一码标准有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。
每个平面有2^16=65536个码位。统一码计划使用了17个平面,一共有17*65536=1114112个码位。在统一码 5.0.0版本中,已定义的码位只有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)的特殊区域。代理区的目的用两个UTF-16字符表示BMP以外的字符。在介绍UTF-16编码时会介绍。
如前所述在统一码5.0.0版本中,238605-65534*2-6400-2408=99089。余下的99089个已定义码位分布在平面0、平面1、平面2和平面14上,它们对应着统一码定义的99089个字符,其中包括71226个汉字。平面0、平面1、平面2和平面14上分别定义了52080、3419、43253和337个字符。平面2的43253个字符都是汉字。平面0上定义了27973个汉字。
实现方式[ | ]
在统一码中,汉字“字”对应的数字是23383。在统一码中,我们有很多方式将数字23383表示成程序中的数据,包括:UTF-8、UTF-16、UTF-32。UTF是“UCS Transformation Format”的缩写,可以翻译成统一码字符集转换格式,即怎样将统一码定义的数字转换成程序数据。例如,“汉字”对应的数字是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个字节。根据字节序的不同,UTF-16可以被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现为UTF-32LE或UTF-32BE。下面介绍UTF-8、UTF-16、UTF-32、字节序和BOM。
UTF-8[ | ]
UTF-8以字节为单位对统一码进行编码。从统一码到UTF-8的编码方式如下:
统一码编码(十六进制)║UTF-8字节流(二进制)
F║0xxxxxxxx║110xxxxx 10xxxxxx║1110xxxx 10xxxxxx 10xxx10xxxx║11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
字节 | 格式 | 实际编码位 | 码点范围 |
---|---|---|---|
1字节 | 0xxxxxxx | 7 | 0 ~ 127 |
2字节 | 110xxxxx 10xxxxxx | 11 | 128 ~ 2047 |
3字节 | 1110xxxx 10xxxxxx 10xxxxxx | 16 | 2048 ~ 65535 |
4字节 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 21 | 65536 ~ 2097151 |
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。统一码的最大码位0x10FFFF也只有21位。
例1:“汉”字的统一码编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001,用这个比特流依次代替模板中的x,得到:1110 0110 1011 0001 1000 1001,即E6 B1 89。
例2:统一码编码0x20C30在0x010000-0x10FFFF之间,使用用4字节模板了:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx。将0x20C30写成21位二进制数字(不足21位就在前面补0):0 0010 0000 1100 0011 0000,用这个比特流依次代替模板中的x,得到:,即F0 A0 B0 B0。
UTF-16[ | ]
UTF-16编码以16位无符号整数为单位。我们把统一码编码记作U。编码规则如下:
如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数(为书写简便,下文将16位无符号整数记作WORD)。
如果U≥0x10000,我们先计算U'=U-0x10000,然后将U'写成二进制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。
为什么U'可以被写成20个二进制位?统一码的最大码位是0x10ffff,减去0x10000后,U'的最大值是0xfffff,所以肯定可以用20个二进制位表示。例如:统一码编码0x20C30,减去0x10000后,得到0x10C30,写成二进制是:0001 0000 1100 0011 0000。用前10位依次替代模板中的y,用后10位依次替代模板中的x,就得到:1101 1000 0100 0011 和 1101 1100 0011 0000,即0xD843 0xDC30。
按照上述规则,统一码编码0x10000-0x10FFFF的UTF-16编码有两个WORD,第一个WORD的高6位是110110,第二个WORD的高6位是110111。可见,第一个WORD的取值范围(二进制)是到1111111111,即0xD800-0xDBFF。第二个WORD的取值范围(二进制)是到11011111 11111111,即0xDC00-0xDFFF。
为了将一个WORD的UTF-16编码与两个WORD的UTF-16编码区分开来,统一码编码的设计者将0xD800-0xDFFF保留下来,并称为代理区(Surrogate):
D800-DB7F ║ High Surrogates ║ 高位替代
DB80-DBFF ║ High Private Use Surrogates ║ 高位专用替代
DC00-DFFF ║ Low Surrogates ║ 低位替代
高位替代就是指这个范围的码位是两个WORD的UTF-16编码的第一个WORD。低位替代就是指这个范围的码位是两个WORD的UTF-16编码的第二个WORD。那么,高位专用替代是什么意思?我们来解答这个问题,顺便看看怎么由UTF-16编码推导统一码编码。
如果一个字符的UTF-16编码的第一个WORD在0xDB80到0xDBFF之间,那么它的统一码编码在什么范围内?我们知道第二个WORD的取值范围是0xDC00-0xDFFF,所以这个字符的UTF-16编码范围应该是0xDB80 0xDC00到0xDBFF 0xDFFF。我们将这个范围写成二进制:110100 - 11
按照编码的相反步骤,取出高低WORD的后10位,并拼在一起,得到0 1111 1111 1111 1111
即0xe0000-0xfffff,按照编码的相反步骤再加上0x10000,得到0xf0000-0x10ffff。这就是UTF-16编码的第一个WORD在0xdb80到0xdbff之间的统一码编码范围,即平面15和平面16。因为统一码标准将平面15和平面16都作为专用区,所以0xDB80到0xDBFF之间的保留码位被称作高位专用替代。
UTF-32[ | ]
UTF-32编码以32位无符号整数为单位。统一码的UTF-32编码就是其对应的32位无符号整数。
根据字节序的不同,UTF-16可以被实现为UTF-16LE或UTF-16BE,UTF-32可以被实现为UTF-32LE或UTF-32BE。例如:
统一码编码║ UTF-16LE ║ UTF-16BE ║ UTF32-LE ║ UTF32-BE
0x006C49 ║ 49 6C ║ 6C 49 ║ 49 6C 00 00 ║ 00 00 6C 49
0x020C30 ║ 43 D8 30 DC ║ D8 43 DC 30 ║ 30 0C 02 00 ║ 00 02 0C 30
判断字节流的字节序[ | ]
统一码标准建议用BOM(Byte Order Mark)来区分字节序,即在传输字节流前,先传输被作为BOM的字符"零宽无中断空格"。这个字符的编码是FEFF,而反过来的FFFE(UTF-16)和FFFE0000(UTF-32)在统一码中都是未定义的码位,不应出现在实际传输中。下表是各种UTF编码的BOM:
UTF编码 ║ Byte Order Mark
UTF-8 ║ EF BB BF
UTF-16LE ║ FF FE
UTF-16BE ║ FE FF
UTF-32LE ║ FF FE 00 00
UTF-32BE ║ 00 00 FE FF
基本上,计算机只是处理数字。它们指定一个数字,来储存字母或其他字符。在创造统一码之前,有数百种指定这些数字的编码系统。没有一个编码可以包含足够的字符:例如,单单欧洲共同体就需要好几种不同的编码来包括所有的语言。即使是单一种语言,例如英语,也没有哪一个编码可以适用于所有的字母,标点符号,和常用的技术符号。这些编码系统也会互相冲突。也就是说,两种编码可能使用相同的数字代表两个不同的字符,或使用不同的数字代表相同的字符。任何一台特定的计算机(特别是服务器)都需要支持许多不同的编码,但是,不论什么时候数据通过不同的编码或平台之间,那些数据总会有损坏的危险。
ASCII码[ | ]
大多数计算机采用美国标准信息交换码(ASCII码),它是表示所有大小写字母、数字、标点符号和控制字符的7位编码方案。统一码包含ASCII码,'\u0000'到'\u007F'对应全部128个ACSII字符。在JAVA中可以使用统一码。
编码范围[ | ]
注:3400-4DBF/4E00-9FFF/20000-3FFFF:中日韩越统一表意文字(CJKV Unified Ideographs)
编码范围
0000-007F:C0控制符及基本拉丁文(C0 Control and Basic Latin)
0080-00FF:C1控制符及拉丁文补充-1(C1 Control and Latin 1 Supplement)
0100-017F:拉丁文扩展-A(Latin Extended-A)
0180-024F:拉丁文扩展-B(Latin Extended-B)
0250-02AF:国际音标扩展(IPA Extensions)
02B0-02FF:空白修饰字母(Spacing Modifiers)
0300-036F:结合用读音符号(Combining Diacritics 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-077F:西非书面语言(N'Ko)
0800-085F:阿维斯塔语及巴列维语(Avestan and Pahlavi)
0860-087F:曼达安语(Mandaic)
0880-08AF:撒马利亚语(Samaritan)
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:哈努诺文(Hanunóo)
1740-175F:布锡文(Buhid)
1760-177F:塔格巴努亚文(Tagbanwa)
1780-17FF:高棉语(Khmer)
1800-18AF:蒙古文(Mongolian)
18B0-18FF:鞑靼语(Cham)
1900-194F:林布文(Limbu)
1950-197F:德宏傣语(Tai Le)
1980-19DF:新傣仂语(New Tai Lue)
19E0-19FF:高棉语记号(Khmer Symbols)
1A00-1A1F:布吉文(Buginese)
1A20-1A5F:巴塔克文(Batak)
1A80-1AEF:兰纳文(Lanna/Tai Tham)
1B00-1B7F:巴厘语(Balinese)
1B80-1BB0:巽他语(Sundanese)
1BC0-1BFF:救世苗文(Pahawh Hmong)
1C00-1C4F:雷布查语(Lepcha)
1C50-1C7F:奥尔其基语字母(Ol Chiki)
1C80-1CDF:曼尼普尔语(Meithei/Manipuri)
1D00-1D7F:语音学扩展(Phonetic Extensions)
1D80-1DBF:语音学扩展补充(Phonetic Extensions Supplement)
1DC0-1DFF:结合用读音符号补充(Combining Diacritics 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 Diacritics Marks for Symbols)
2100-214F:字母式符号(Letterlike Symbols)
2150-218F:数字形式(Number Form)
2190-21FF:箭头(Arrows)
2200-22FF:数学运算符(Mathematical Operator)
2300-23FF:杂项工业符号(Miscellaneous Technical)
2400-243F:控制图片(Control Pictures)
2440-245F:光学识别符(Optical Character Recognition)
2460-24FF:封闭式字母数字(Enclosed Alphanumerics)
2500-257F:制表符(Box Drawing)
2580-259F:方块元素(Block Element)
25A0-25FF:几何图形(Geometric Shapes)
2600-26FF:杂项符号(Miscellaneous Symbols)
2700-27BF:印刷符号(Dingbats)
27C0-27EF:杂项数学符号-A(Miscellaneous Mathematical Symbols-A)
27F0-27FF:追加箭头-A(Supplemental Arrows-A)
2800-28FF:盲文点字模型(Braille Patterns)
2900-297F:追加箭头-B(Supplemental Arrows-B)
2980-29FF:杂项数学符号-B(Miscellaneous Mathematical Symbols-B)
2A00-2AFF:追加数学运算符(Supplemental Mathematical Operator)
2B00-2BFF:杂项符号和箭头(Miscellaneous Symbols and Arrows)
2C00-2C5F:格拉哥里字母(Glagolitic)
2C60-2C7F:拉丁文扩展-C(Latin Extended-C)
2C80-2CFF:古埃及语(Coptic)
2D00-2D2F:格鲁吉亚语补充(Georgian Supplement)
2D30-2D7F:提非纳文(Tifinagh)
2D80-2DDF:埃塞俄比亚语扩展(Ethiopic Extended)
2E00-2E7F:追加标点(Supplemental Punctuation)
2E80-2EFF:CJK部首补充(CJK Radicals Supplement)
2F00-2FDF:康熙字典部首(Kangxi Radicals)
2FF0-2FFF:表意文字描述符(Ideographic Description Characters)
3000-303F:CJK符号和标点(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笔画(CJK Strokes)
31F0-31FF:日文片假名语音扩展(Katakana Phonetic Extensions)
3200-32FF:封闭式CJK文字和月份(Enclosed CJK Letters and Months)
3300-33FF:CJK兼容(CJK Compatibility)
3400-4DBF:CJK统一表意符号扩展-A(CJK Unified Ideographs Extension-A)
4DC0-4DFF:易经六十四卦符号(Yijing Hexagrams Symbols)
4E00-9FFF:CJK统一表意符号(CJK Unified Ideographs)
A000-A48F:彝文音节(Yi Syllables)
A490-A4CF:彝文字根(Yi Radicals)
A500-A61F:瓦伊语(Vai)
A660-A6FF:统一加拿大土著语音节补充(Unified Canadian Aboriginal Syllabics Supplement)
A700-A71F:声调修饰字母(Modifier Tone Letters)
A720-A7FF:拉丁文扩展-D(Latin Extended-D)
A800-A82F:锡尔赫特文字母(Syloti Nagri)
A840-A87F:八思巴字(Phags-pa)
A880-A8DF:索拉什特拉语Saurashtra
A900-A97F:爪哇语(Javanese)
A980-A9DF:查克玛语(Chakma)
AA00-AA3F:Varang Kshiti
AA40-AA6F:索拉索姆字母(Sorang Sompeng)
AA80-AADF:尼瓦尔语(Newari)
AB00-AB5F:越南傣语(Vi?t Thái)
AB80-ABA0:克耶字母(Kayah Li)
AC00-D7AF:朝鲜文音节(Hangul Syllables)
D800-DBFF:High-half zone of UTF-16
DC00-DFFF:Low-half zone of UTF-16
E000-F8FF:自行使用区域(Private Use Zone)
F900-FAFF:CJK兼容象形文字(CJK Compatibility Ideographs)
FB00-FB4F:字母表达形式(Alphabetic Presentation Form)
FB50-FDFF:阿拉伯表达形式A(Arabic Presentation Form-A)
FE00-FE0F:变量选择符(Variation Selector)
FE10-FE1F:竖排形式(Vertical Forms)
FE20-FE2F:组合用半符号(Combining Half Marks)
FE30-FE4F:CJK兼容形式(CJK Compatibility Forms)
FE50-FE6F:小型变体形式(Small Form Variants)
FE70-FEFF:阿拉伯表达形式B(Arabic Presentation Form-B)
FF00-FFEF:半型及全型形式(Halfwidth and Fullwidth Form)
FFF0-FFFF:特殊(Specials)
10000–1FFFF:第1辅助平面,多文种补充平面(Supplementary Multilingual Plane, SMP)
20000–2FFFF:第2辅助平面,表意文字补充平面(Supplementary Ideographic Plane, SIP)
30000–3FFFF:第3辅助平面,表意文字第三平面(Tertiary Ideographic Plane, TIP)
40000–DFFFF:第4-13辅助平面,尚未使用
E0000–EFFFF:第14辅助平面,特别用途补充平面(Supplementary Special-purpose Plane, SSP)
F0000–FFFFF:第15辅助平面,保留作为私人使用区(Private Use Area, PUA)
100000–10FFFF:第16辅助平面,保留作为私人使用区(Private Use Area, PUA)
统一码编码原则[ | ]
Universality:提供单一、综合的字符集,编码一切现代与大部分历史文献的字符。
Efficiency:易于处理与分析。
Characters, not glyphs:字符,而不是字形。
Semantics:字符要有良好定义的语义。
Plain text:仅限于文本字符。
Logical order:默认内存表示是其逻辑序。
Unification:把不同语言的同一书写系统(scripts)中相同字符统一起来。
Dynamic composition:附加符号可以动态组合。
Stability:已分配的字符与语义不再改变。
Convertibility:统一码与其他著名字符集可以精确转换。
本文章来自 Unicode 字符 wiki,转载自Reo Naisu(Uni字符wiki是人造语言 维基的子维基)