Unicode UTF-16 UTF-8 GB2312 GBK GB18030 ASCII Latin-1

整理一下这些概念。

计算机内只能保存101010等二进制数据,那么页面上显示的字符是如何显示出来的呢?1

一:字符集(Charset)
charset = char + set,char 是字符,set是集合,charset就是字符的集合。
字符集就是是这个编码方式涵盖了哪些字符,每个字符都有一个数字序号。

二:编码方式(Encoding)
编码方式就是一个字符要怎样编码成二进制字节序,或者反过来怎么解析。
也即给你一个数字序号,要编码成几个字节,字节顺序如何,或者其他特殊规则。

三:字形字体(Font)
根据数字序号调用字体存储的字形,就可以在页面上显示出来了。
所以一个字符要显示出来,要显示成什么样子要看字体文件。

综上所述,Unicode 只是字符集,而没有编码方式。
UTF-8 是一种 Unicode 字符集的编码方式,其他还有 UTF-16,UTF-32 等。
而有了字符集以及编码方式,如果系统字体是没有这个字符,也是显示不出来的。

Unicode 字符编码标准2

Unicode(中文:万国码、国际码、统一码、单一码)是计算机科学领域里的一项业界标准。

简介:

大概来说,Unicode编码系统可分为编码方式和实现方式两个层次。

编码方式 3

Unicode是为整合全世界的所有语言文字而诞生的。任何字符在Unicode中都对应一个值。这个值就可以称为这个字符的Unicode值。

ISO制定了通用字符集(Universal Character SetUCS)。UCS包括UCS-2UCS-4

UCS-2用两个字节编码。取值范围为 U+0000U+FFFF

UCS-4用四个字节编码。它的范围为 U+00000000U+7FFFFFFF,其中 U+00000000U+0000FFFF和UCS-2是一样的。

要注意,UCS-2UCS-4只规定了Unicode值和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为UTF(Unicode Transformation Format),其中应用较多的就是UTF-16UTF-8了。

实现方式

Unicode的实现方式不同于编码方式。一个字符的Unicode值是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对Unicode编码的实现方式有所不同。Unicode的实现方式称为Unicode转换格式Unicode Transformation Format,简称为UTF)。

例如,如果一个仅包含基本7位ASCII字符的Unicode文件,如果每个字符都使用2字节的原Unicode编码传输,其第一字节的8位始终为0。这就造成了比较大的浪费。对于这种情况,可以使用UTF-8编码,这是一种变长编码,它将基本7位ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他Unicode字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为0或1进行识别。这样对以7位ASCII字符为主的西文文档就大幅节省了编码长度(具体方案参见UTF-8)。类似的,对未来会出现的需要4个字节的辅助平面字符和其他UCS-4扩充字符,2字节编码的UTF-16也需要通过一定的算法进行转换。

再如,如果直接使用与Unicode编码一致(仅限于BMP字符)的UTF-16编码,由于每个字符占用了两个字节,在Mac机和个人电脑上,对字节顺序的理解是不一致的。这时同一字节流可能会被解释为不同内容,如某字符为十六进制编码4E59,按两个字节拆分为4E和59,在Mac上读取时是从低字节开始,那么在Mac OS会认为此4E59编码为594E,找到的字符为“奎”,而在Windows上从高字节开始读取,则编码为U+4E59的字符为“乙”。就是说在Windows下以UTF-16编码保存一个字符“乙”,在Mac OS环境下打开会显示成“奎”。此类情况说明UTF-16的编码顺序若不加以人为定义就可能发生混淆,于是在UTF-16编码实现方式中使用了大端序(Big-Endian,简写为UTF-16 BE)、小端序(Little-Endian,简写为UTF-16 LE)的概念,以及可附加的字节顺序记号解决方案,目前在PC机上的Windows系统和Linux系统对于UTF-16编码默认使用UTF-16 LE。(具体方案参见UTF-16

此外Unicode的实现方式还包括UTF-7PunycodeCESU-8SCSUUTF-32GB18030等,这些实现方式有些仅在一定的国家和地区使用,有些则属于未来的规划方式。目前通用的实现方式是UTF-16小端序(LE)、UTF-16大端序(BE)和UTF-8。在微软公司Windows XP附带的记事本(Notepad)中,“另存为”对话框可以选择的四种编码方式除去非Unicode编码的ANSI(对于英文系统即ASCII编码,中文系统则为GB2312Big5编码)外,其余三种为Unicode(对应UTF-16 LE)、Unicode big endian(对应UTF-16 BE)和UTF-8

关于Big EndianLittle Endian

一个字符可能占用多个字节,那么这多个字节在计算机中如何存储呢?比如字符0xABCD,它的存储格式到底是AB CD,还是CD AB 呢?实际上两者都有可能,并分别有不同的名字。如果存储为AB CD,则称为Big Endian;如果存储为 CD AB,则称为Little Endian

具体来说,以下这种存储格式为Big Endian,因为值(0xABCD)的高位(0xAB)存储在前面:

地址
0x00000000 AB
0x00000001 CD

相反,以下这种存储格式为Little Endian

地址
0x00000000 CD
0x00000001 AB

Unicode编码方法

ASCII4

简介

ASCII定义了128个字符;其中33个字符无法显示(一些终端提供了扩展,使得这些字符可显示为诸如笑脸、扑克牌花式等8-bit符号),且这33个字符多数都已是陈废的控制字符。控制字符的用途主要是用来操控已经处理过的文字。在33个字符之外的是95个可显示的字符,包含用键盘敲下空白键所产生的空白字符也算1个可显示字符(显示为空白)。

缺点

ASCII的局限在于只能显示26个基本拉丁字母、阿拉伯数目字和英式标点符号,因此只能用于显示现代美国英语(而且在处理英语当中的外来词如naïve、café、élite等等时,所有重音符号都不得不去掉,即使这样做会违反拼写规则)。而EASCII虽然解决了部分西欧语言的显示问题,但对更多其他语言依然无能为力。

编码单位长度

7bit 占用一个字节,第一位二进制为0。

0XXX XXXX  //二进制
↑第一位为0,所以总数为128个

编码范围

编码范围:0000 0000 ~ 0111 1110

其中可控字符范围是:0000 0000 ~ 0001 11110111 1111

可显示字符范围是:0010 0000 ~ 0111 1110

UTF-85

UTF-88-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部分修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或发送文字的应用中,优先采用的编码。

UTF-8应该是目前应用最广泛的一种Unicode编码方案。由于UCS-2/UTF-16对于ASCII字符使用两个字节进行编码,存储和处理效率相对低下,并且由于ASCII字符经过UTF-16编码后得到的两个字节,高字节始终是0x00,很多C语言的函数都将此字节视为字符串末尾从而导致无法正确解析文本。因此一开始推出的时候遭到很多西方国家的抵触,大大影响了Unicode的推行。后来聪明的人们发明了UTF-8编码,解决了这个问题。

说明:UTF-8使用一至六个字节为每个字符编码,但是2003年11月UTF-8RFC 3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF。

编码单位长度

8bit * 1~6

or

8bit * 1~4 (RFC 3629重新规范)

Unicode值转换图(编码范围)

Unicode符号范围 UTF-8编码方式
(十六进制) (二进制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

一张更加详细的转换图

unicode-to-utf8

对于ASCII字符的编码使用单字节,和ASCII编码一摸一样,这样所有原先使用ASCII编解码的文档就可以直接转到UTF-8编码了。对于其他字符,则使用2-4个字节来表示,其中,首字节前置1的数目代表正确解析所需要的字节数,剩余字节的高2位始终是10。例如首字节是1110yyyy,前置有3个1,说明正确解析总共需要3个字节,需要和后面2个以10开头的字节结合才能正确解析得到字符。

UTF-8 没有Big EndianLittle Endian问题。

UTF-16

基本多语言平面(Basic Multilingual Plane, BMP)

Unicode的编码空间从U+0000U+10FFFF,共有1,112,064个码位(code point)可用来映射字符. Unicode的编码空间可以划分为17个平面(plane),每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000U+xxFFFF,其中xx表示十六进制值从0016到1016,共计17个平面。第一个平面称为基本多语言平面(Basic Multilingual Plane, BMP),或称第零平面(Plane 0)。其他平面称为辅助平面(Supplementary Planes)。基本多语言平面内,从U+D800U+DFFF之间的码位区段是永久保留不映射到Unicode字符。UTF-16就利用保留下来的0xD800-0xDFFF区段的码位来对辅助平面的字符的码位进行编码。

UTF-16与UCS-2的关系

UTF-16可看成是UCS-2的父集。在没有辅助平面字符(surrogate code points)前,UTF-16UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支持UCS-2编码,那其实是暗指它不能支持在UTF-16中超过2bytes的字集。对于小于0x10000UCS码,UTF-16编码就等于UCS码。

编码模式

UTF-16Big EndianLittle Endian存储形式都在用。一般来说,以Macintosh制作或存储的文字使用Big Endian格式,以Microsoft或Linux制作或存储的文字使用Little Endian格式。

为了弄清楚UTF-16文件的大小尾序(Big EndianLittle Endian),在UTF-16文件的开首,都会放置一个U+FEFF字符作为Byte Order MarkUTF-16LEFF FE代表,UTF-16BEFE FF代表),以显示这个文本文件是以UTF-16编码,其中U+FEFF字符在UNICODE中代表的意义是ZERO WIDTH NO-BREAK SPACE,顾名思义,它是个没有宽度也没有断字的空白。

以下的例子有四个字符:“朱”(U+6731)、半角逗号(U+002C)、“聿”(U+807F)。

编码名称 编码次序 BOM ,
UTF-16LE 小尾序,不含BOM 31 67 2C 00 7F 80 69 D8
UTF-16BE 大尾序,不含BOM 67 31 00 2C 80 7F D8 69
UTF-16LE 小尾序,包含BOM FF FE 31 67 2C 00 7F 80
UTF-16BE 大尾序,包含BOM FE FF 67 31 00 2C 80 7F

编码单位长度

16bit

32bit

UTF-16无法兼容于ASCII编码。

编码范围

16进制编码范围 UTF-16表示方法(二进制) 10进制码范围 字节数量
U+0000---U+FFFF xxxxxxxx xxxxxxxx yyyyyyyy yyyyyyyy 0-65535 2
U+10000---U+10FFFF 110110yyyyyyyyyy 110111xxxxxxxxxx 65536-1114111 4

UTF-16比起UTF-8,好处在于大部分字符都以固定长度的字节(2字节)存储。

Unicode值转换方法请移步伪基。

GB2312

简介

GB2312标准共收录6763个汉字,其中一级汉字3755个,二级汉字3008个;同时收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个字符。

GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。但对于人名、古汉语等方面出现的罕用字和繁体字,GB2312不能处理,因此后来GBKGB18030汉字字符集相继出现以解决这些问题。

分区表示

GB2312中对所收汉字进行了“分区”处理,每区含有94个汉字/符号。这种表示方式也称为区位码。

  • 01–09区为特殊符号。
  • 16–55区为一级汉字,按拼音排序。
  • 56–87区为二级汉字,按部首/笔画排序。

举例来说,“啊”字是GB2312之中的第一个汉字,它的区位码就是1601。

10–15区及88–94区则未有编码。但在附录3,则在第10区推荐作为 GB1988–80 中的94个图形字符区域(即第3区字符之半形版本)。

字节结构

在使用GB2312的程序通常采用EUC储存方法,以便兼容于ASCII。浏览器编码表上的GB2312,通常都是指EUC-CN表示法。

每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”,第二个字节称为“低位字节”。

“高位字节”使用了0xA10xF7(把01–87区的区号加上0xA0),“低位字节”使用了0xA10xFE(把01–94加上0xA0)。 由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB00xF7,“低位字节”的范围是0xA10xFE,占用的码位是72*94=6768。其中有5个空位是D7FAD7FE

例如“啊”字在大多数程序中,会以两个字节,0xB0(第一个字节)0xA1(第二个字节)储存。(与区位码对比:0xB0=0xA0+16,0xA1=0xA0+1)。

编码单位长度

8bit (兼容 ACSII

16bit

编码范围

GB2312编码范围:0xA1A10xFEFE,其中汉字编码范围:0xB0A1-0xF7FE

GB2312有两种编码实现,只有其中一种被 GBK / GB18030 兼容。详情请查看下方伪基链接。

GBK6

GBK即汉字内码扩展规范,K为汉语拼音Kuo Zhan(扩展)中“扩”字的声母。英文全称Chinese Internal Code Specification

编码单位长度

8bit

16bit

编码方式

字符有一字节和双字节编码,00–7F范围内是第一个字节,和ASCII保持一致,此范围内严格上说有96个文字和32个控制符号。

之后的双字节中,前一字节是双字节的第一位。总体上说第一字节的范围是81–FE(也就是不含80和FF),第二字节的一部分领域在40–7E,其他领域在80–FE。

具体来说,定义的是下列字节:

编码范围

范围 第1字节 第2字节 编码数 字数
水准GBK/1 A1–A9 A1–FE 846 717
水准GBK/2 B0–F7 A1–FE 6,768 6,763
水准GBK/3 81–A0 40–FE (7F除外) 6,080 6,080
水准GBK/4 AA–FE 40–A0 (7F除外) 8,160 8,160
水准GBK/5 A8–A9 40–A0 (7F除外) 192 166
用户定义 AA–AF A1–FE 564
用户定义 F8–FE A1–FE 658
用户定义 A1–A7 40–A0 (7F除外) 672
合计: 23,940 21,886

与其他编码的关系

GBK向下完全兼容GB2312-80编码。支持GB2312-80编码不支持的部分中文姓,中文繁体,日文假名,还包括希腊字母以及俄语字母等字母。不过这种编码不支持韩国字,也是其在实际使用中与unicode编码相比欠缺的部分。

GB180307

GB18030,全称:国家标准GB18030-2005《信息技术 中文编码字符集》,是中华人民共和国现时最新的内码字集,是GB18030-2000《信息技术 信息交换用汉字编码字符集 基本集的扩充》的修订版。与GB2312-1980完全兼容,与GBK基本兼容,支持GB13000Unicode的全部统一汉字,共收录汉字70,244个。

GB18030主要有以下特点:

  • UTF-8 相同,采用多字节编码,每个字可以由1个、2个或4个字节组成。
  • 编码空间庞大,最多可定义161万个字元。
  • 支持中国国内少数民族的文字,不需要动用造字区。
  • 汉字收录范围包含繁体汉字以及日韩汉字。

任何能够将Unicode字符映射为字节流的编码都属于Unicode编码。中国的GB18030编码,覆盖了Unicode所有的字符,因此也算是一种Unicode编码。只不过他的编码方式并不像UTF-8或者UTF-16一样,将Unicode字符的编号通过一定的规则进行转换,而只能通过查表的手段进行编码。

编码单位长度

8bit

16bit

32bit

编码范围

  • 单字节,其值从0x000x7F
  • 双字节,第一个字节的值从0x810xFE,第二个字节的值从0x400xFE(不包括0x7F)。
  • 四字节,第一个字节的值从0x810xFE,第二个字节的值从0x300x39,第三个字节从0x810xFE,第四个字节从0x300x39

Latin-18

ISO 8859-1,正式编号为ISO/IEC 8859-1:1998,又称Latin-1西欧语言,是国际标准化组织内ISO/IEC 8859的第一个8位字符集。它以ASCII为基础,在空置的0xA0-0xFF的范围内,加入96个字母及符号,藉以供使用附加符号的拉丁字母语言使用。曾推出过ISO 8859-1:1987版。

其他读物

字符编解码的故事(ASCII,ANSI,Unicode,Utf-8区别)

关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)

深度剖析Java的字符编码

标签:utf16, utf8, gb2312, gbk, gb18030, unicode, ascii, latin1