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 Set
,UCS
)。UCS
包括UCS-2
和UCS-4
。
UCS-2
用两个字节编码。取值范围为 U+0000
~U+FFFF
。
UCS-4
用四个字节编码。它的范围为 U+00000000
~U+7FFFFFFF
,其中 U+00000000
~U+0000FFFF
和UCS-2是一样的。
要注意,UCS-2
和UCS-4
只规定了Unicode
值和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为UTF(Unicode Transformation Format
),其中应用较多的就是UTF-16
和UTF-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-7
、Punycode
、CESU-8
、SCSU
、UTF-32
、GB18030
等,这些实现方式有些仅在一定的国家和地区使用,有些则属于未来的规划方式。目前通用的实现方式是UTF-16
小端序(LE)、UTF-16
大端序(BE)和UTF-8
。在微软公司Windows XP附带的记事本(Notepad)中,“另存为”对话框可以选择的四种编码方式除去非Unicode
编码的ANSI
(对于英文系统即ASCII
编码,中文系统则为GB2312
或Big5
编码)外,其余三种为Unicode
(对应UTF-16 LE
)、Unicode big endian
(对应UTF-16 BE
)和UTF-8
。
关于Big Endian
和Little 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 1111
和 0111 1111
可显示字符范围是:0010 0000
~ 0111 1110
UTF-85
UTF-8
(8-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-8
被RFC 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 |
一张更加详细的转换图
对于ASCII
字符的编码使用单字节,和ASCII
编码一摸一样,这样所有原先使用ASCII
编解码的文档就可以直接转到UTF-8编码了。对于其他字符,则使用2-4个字节来表示,其中,首字节前置1的数目代表正确解析所需要的字节数,剩余字节的高2位始终是10。例如首字节是1110yyyy,前置有3个1,说明正确解析总共需要3个字节,需要和后面2个以10开头的字节结合才能正确解析得到字符。
UTF-8
没有Big Endian
和Little Endian
问题。
UTF-16
基本多语言平面(Basic Multilingual Plane, BMP)
Unicode
的编码空间从U+0000
到U+10FFFF
,共有1,112,064个码位(code point
)可用来映射字符. Unicode
的编码空间可以划分为17个平面(plane
),每个平面包含216(65,536)个码位。17个平面的码位可表示为从U+xx0000
到U+xxFFFF
,其中xx表示十六进制值从0016到1016,共计17个平面。第一个平面称为基本多语言平面(Basic Multilingual Plane
, BMP
),或称第零平面(Plane 0)。其他平面称为辅助平面(Supplementary Planes
)。基本多语言平面内,从U+D800
到U+DFFF
之间的码位区段是永久保留不映射到Unicode
字符。UTF-16
就利用保留下来的0xD800
-0xDFFF
区段的码位来对辅助平面的字符的码位进行编码。
UTF-16与UCS-2的关系
UTF-16
可看成是UCS-2
的父集。在没有辅助平面字符(surrogate code points
)前,UTF-16
与UCS-2
所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16
了。现在若有软件声称自己支持UCS-2
编码,那其实是暗指它不能支持在UTF-16
中超过2bytes
的字集。对于小于0x10000
的UCS
码,UTF-16
编码就等于UCS
码。
编码模式
UTF-16
的Big Endian
和Little Endian
存储形式都在用。一般来说,以Macintosh制作或存储的文字使用Big Endian
格式,以Microsoft或Linux制作或存储的文字使用Little Endian
格式。
为了弄清楚UTF-16
文件的大小尾序(Big Endian
和Little Endian
),在UTF-16
文件的开首,都会放置一个U+FEFF
字符作为Byte Order Mark
(UTF-16LE
以FF FE
代表,UTF-16BE
以FE 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
不能处理,因此后来GBK
及GB18030
汉字字符集相继出现以解决这些问题。
分区表示
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
表示法。
每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”,第二个字节称为“低位字节”。
“高位字节”使用了0xA1
–0xF7
(把01–87区的区号加上0xA0
),“低位字节”使用了0xA1
–0xFE
(把01–94加上0xA0
)。 由于一级汉字从16区起始,汉字区的“高位字节”的范围是0xB0
–0xF7
,“低位字节”的范围是0xA1
–0xFE
,占用的码位是72*94=6768。其中有5个空位是D7FA
–D7FE
。
例如“啊”字在大多数程序中,会以两个字节,0xB0
(第一个字节)0xA1
(第二个字节)储存。(与区位码对比:0xB0=0xA0+16,0xA1=0xA0+1)。
编码单位长度
8bit
(兼容 ACSII
)
16bit
编码范围
GB2312
编码范围:0xA1A1
-0xFEFE
,其中汉字编码范围: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
基本兼容,支持GB13000
及Unicode
的全部统一汉字,共收录汉字70,244个。
GB18030
主要有以下特点:
- 与
UTF-8
相同,采用多字节编码,每个字可以由1个、2个或4个字节组成。 - 编码空间庞大,最多可定义161万个字元。
- 支持中国国内少数民族的文字,不需要动用造字区。
- 汉字收录范围包含繁体汉字以及日韩汉字。
任何能够将Unicode
字符映射为字节流的编码都属于Unicode
编码。中国的GB18030
编码,覆盖了Unicode
所有的字符,因此也算是一种Unicode
编码。只不过他的编码方式并不像UTF-8
或者UTF-16
一样,将Unicode
字符的编号通过一定的规则进行转换,而只能通过查表的手段进行编码。
编码单位长度
8bit
16bit
32bit
编码范围
- 单字节,其值从
0x00
到0x7F
。 - 双字节,第一个字节的值从
0x81
到0xFE
,第二个字节的值从0x40
到0xFE
(不包括0x7F
)。 - 四字节,第一个字节的值从
0x81
到0xFE
,第二个字节的值从0x30
到0x39
,第三个字节从0x81
到0xFE
,第四个字节从0x30
到0x39
。
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区别)