【字符编码系列】常用的几种字符编码(GBK,UTF-8,UTF-16)

| 分类 blog  | 标签 字符编码  | 浏览  
字符编码

引言

如果不知道是什么编码,先试试UTF-8!

写在前面的话

本文属于 字符编码系列文章之一,更多请前往 字符编码系列

题纲

  • 基本概念
  • 欧美的编码
    • ASCII码
    • ISO-8859-1编码
  • 中文系列编码
    • GB2312编码
    • GBK编码
    • BIG5编码
    • GB18030编码
    • ANSI 编码
  • Unicode与UCS
  • Unicode标准
  • Unicode编码的不同实现
    • UTF-8编码
    • UTF-16编码
    • UTF-32编码

基本概念

关于字符编码的简介以及发展编年史可以参考 【字符编码系列】字符,字符集,字符编码解惑

本文主要详细介绍各个编码的特点以及实现。

欧美的编码

ASCII码

简介

(American Standand Code for InformationInterchange)的缩写

ASCII码是计算机最开始支持的基于拉丁字母的编码,一个字符用一个字节表示,只用了低7位,最高位为0,因此总共有128个ASCII码,范围为0~127。

编码范围

0~127(总共有128个ASCII码),详情百度(google)ASCII码表

适用范围以及存在问题

适用于现代英文和其它西欧语言

但是由于编码范围有限,所以无法支持多种地区的语言,后来就产生了各种其它的编码方案

特性

单字节编码

只占用一个字节

高位不占用,最多为(01111111)

ISO-8859-1编码

简介

即”标准码”,通常叫做Latin-1

ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号

编码范围

0x00-0xFF(0-255)

适用范围以及存在问题

此字符集支持部分于欧洲使用的语言,包括阿尔巴尼亚语、巴斯克语、布列塔尼语、加泰罗尼亚语、丹麦语、荷兰语、法罗语、弗里西语、加利西亚语、德语、格陵兰语、冰岛语、爱尔兰盖尔语、意大利语、拉丁语、卢森堡语、挪威语、葡萄牙语、里托罗曼斯语、苏格兰盖尔语、西班牙语及瑞典语。

但是不支持中文和东亚等国的语言.

特性

单字节编码

只占用一个字节

高位可以用,最多为(11111111)

中文编码系列

GB2312编码

简介

GB是”国标”两字的拼音首字,2312是标准序号

GB2312编码是第一个汉字编码国家标准,由中国国家标准总局1980年发布,1981年5月1日开始使用。GB2312编码共收录汉字6763个,其中一级汉字3755个,二级汉字3008个。同时,GB2312编码收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

(GB2312中的字符是全角字符,ASCII原始的字符是半角字符)

编码范围

A1A1-FEFE(41377-65278)

其中汉字编码范围:B0A1-F7FE(45217-63486)。

适用范围以及存在问题

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

中国大陆几乎所有的中文系统和国际化的软件都支持GB 2312

特性

分区表示

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

01-09区收录除汉字外的682个字符。

10-15区为空白区,没有使用。

16-55区收录3755个一级汉字,按拼音排序。

56-87区收录3008个二级汉字,按部首/笔画排序。

88-94区为空白区,没有使用。

举例来说,“啊”字是GB2312编码中的第一个汉字,它位于16区的01位,所以它的区位码就是1601

双字节编码

GB2312规定对收录的每个字符采用两个字节表示,第一个字节为“高字节”,对应94个区;第二个字节为“低字节”,对应94个位。所以它的区位码范围是:0101-9494。区号和位号分别加上0xA0就是GB2312编码。例如最后一个码位是9494,区号和位号分别转换成十六进制是5E5E,0x5E+0xA0=0xFE,所以该码位的GB2312编码是FEFE。

GB2312编码范围:A1A1-FEFE,其中汉字的编码范围为B0A1-F7FE,第一字节0xB0-0xF7(对应区号:16-87),第二个字节0xA1-0xFE(对应位号:01-94)

GBK编码

简介

即汉字国标扩展码,

GBK编码,是对GB2312编码的扩展,因此完全兼容GB2312-80标准。GBK编码依然采用双字节编码方案,其编码范围:8140-FEFE,剔除xx7F码位,共23940个码位。共收录汉字和图形符号21886个,其中汉字(包括部首和构件)21003个,图形符号883个。GBK编码支持国际标准ISO/IEC10646-1和国家标准GB13000-1中的全部中日韩汉字,并包含了BIG5编码中的所有汉字。GBK编码方案于1995年12月15日正式发布,这一版的GBK规范为1.0版。

Windows 95系统就是以GBK为内码,又由于GBK同时也涵盖了Unicode所有CJK汉字,所以也可以和Unicode做一一对应

编码范围

8140-FEFE (33088-65278)

全部编码分为三大部分:1.汉字区;2.图形符号区;3.用户自定义区(详情见特性码位分配及顺序)

适用范围以及存在问题

几乎完美支持汉字,但是不支持部分国家的语言(如一些东亚国家,日本等)

所以经常会有GBK到UNICODE的转换

特性

字汇

GBK 规范收录了 ISO 10646.1 中的全部 CJK 汉字和符号,并有所补充。具体包括:

  1. GB 2312 中的全部汉字、非汉字符号。
  2. GB 13000.1 中的其他 CJK 汉字。以上合计 20902 个 GB 化汉字。
  3. 《简化字总表》中未收入 GB 13000.1 的 52 个汉字。
  4. 《康熙字典》及《辞海》中未收入 GB 13000.1 的 28 个部首及重要构件。
  5. 13 个汉字结构符。
  6. BIG-5 中未被 GB 2312 收入、但存在于 GB 13000.1 中的 139 个图形符号。
  7. GB 12345 增补的 6 个拼音符号。
  8. 汉字“○”。
  9. GB 12345 增补的 19 个竖排标点符号(GB12345 较 GB 2312 增补竖排标点符号 29 个,其中 10 个未被 GB 13000.1 收入,故 GBK 亦不收)。
  10. 从 GB 13000.1 的 CJK 兼容区挑选出的 21 个汉字。
  11. GB 13000.1 收入的 31 个 IBM OS/2 专用符号。
  12. 未录入《新华字典》上的一些字,如“韡”的简体。
码位分配及顺序

GBK 亦采用双字节表示,总体编码范围为 8140-FEFE,首字节在 81-FE 之间,尾字节在 40-FE 之间,剔除 xx7F 一条线。总计 23940 个码位,共收入 21886 个汉字和图形符号,其中汉字(包括部首和构件)21003 个,图形符号 883 个。

误处理

低字节是0x40-0x7E的GBK字符有一定特殊性,因为这些字符占用了ASCII码的位置,这样会给一些系统带来麻烦。

有些系统中用0x40-0x7E中的字符(如“ ”)做特殊符号,在定位这些符号时又没有判断这些符号是不是属于某个 GBK字符的低字节,这样就会造成错误判断。在支持GB2312的环境下就不存在这个问题。需要注意的是支持GBK的环境中小于0x80的某个字节未必就 是ASCII符号;另外就是最好选用小于0×40的ASCII符号做一些特殊符号,这样就可以快速定位,且不用担心是某个汉字的另一半。Big5编码中也存在相应问题。
双字节编码

遵循GB2312规定

BIG5 编码

简介

BIG5编码又称大五码,是繁体中文字符集编码标准,共收录13060个中文字,其中有二字为重复编码。

BIG5重复地收录了两个相同的字:“兀、兀”(A461及C94A)、“嗀、嗀”(DCD1及DDFC)。

编码范围

8140-FEFE(33088-65278)

其中汉字编码范围:A440-F9DC(42048-63964)

BIG5采用双字节编码,使用两个字节来表示一个字符。高位字节使用了0x81-0xFE,低位字节使用了0x40-0x7E,及0xA1-0xFE

适用范围以及存在问题

适用于台湾和香港地区的繁体中文系统软件等.不过由于编码本身存在的问题.已经基本改用Unicode编码了.

兼容问题

由于各厂商及政府推出的Big5延伸,彼此互不兼容,造成乱码问题。

冲码问题

因为低位元字符中包含了编程语言、shell、script 中,字串或命令常会用到的特殊字符,例如0x5C “\”、0x7C “|”等。“\”在许多用途的字串中是当作转义符号又称为跳脱字符,例如 \n(换行)、\r(归位)、\t(tab)、\(\本身符号)、"(引号)等等。而 “|” 在UNIX操作系统中大多当作命令管线的使用,如 “ls -la | more” 等等。如果在字串中有这些特殊的转义字符,会被程式或直译器解释为特殊用途。但是因为是中文的原因,故无法正确解释为上面所述的行为,因此程式可能会忽略此转义符号或是中断执行。若此,就违反了使用者本来要当成中文字符一部份使用的本意。

在常用字如“功”(0xA55C)、“许”(0xB35C)、“盖”(0xBB5C)、“育”(0xA87C)中时常出现,造成了许多软件无法正确处理以Big5编码的字串或文件。这个问题被戏谑性地人名化,称为“许功盖”或“许盖功”(这三个字都有这种问题)。但是额外的困扰是,有些输出功能并不会把“\”当作特殊字符看待,所以有些程式或网页就会错误地常常出现在“许功盖”这些字后面多了“\”。

私人造字

在倚天中文系统,以及后来的Windows3.1、95及98中,定义了四个私人造字区范围:0xFA40-0xFEFE、0x8E40-0xA0FE、0x8140-0x8DFE、0xC6A1-0xC8FE。私人造字区的原意,是供使用者加入本来在编码表中缺少的字符,但当每个使用者都在不同的地方加上不同的字符后,当交换资料时,对方便难以知道某一个编码究竟想表达什么字

特性

双字节编码

Big5是双字节编码,高字节编码范围是0x81-0xFE,低字节编码范围是0x40-0x7E和0xA1-0xFE。和GBK相比,少了低字节是0x80-0xA0的组合。0x8140-0xA0FE是保留区域,用于用户造字区

字符有限

Big5收录的汉字只包括繁体汉字,不包括简体汉字,一些生僻的汉字也没有收录。GBK收录的日文假名字符、俄文字符Big5也没有收录。因为Big5当中收录的字符有限,因此有很多在Big5基础上扩展的编码,如倚天中文系统。Windows系统上使用的代码页CP950也可以理解为是对Big5的扩展,在Big5的基础上增加了7个汉字和一些符号。Big5编码对应的字符集是GBK字符集的子集,也就是说Big5收录的字符是GBK收录字符的一部分,但相同字符的编码不同。

误处理

因为Big5也占用了ASCII的编码空间(低字节所使用的0x40-0x7E),所以Big5编码在一些环境下存在和GBK编码相同的问题,即低字节范围为0x40-0x7E的字符有可能会被误处理,尤其是低字节是0x5C(”/”)和0x7C(”|”)的字符。可以参考GBK一节相应说明。

GB18030编码

简介

2000年3月17日发布的汉字编码国家标准GB18030编码,是对GBK编码的扩充,覆盖中文、日文、朝鲜语和中国少数民族文字,其中收录27484个汉字。GB18030字符集采用单字节、双字节和四字节三种方式对字符编码。兼容GBK和GB2312字符集。

它完全兼容ASCII码与GBK码。

编码范围

采用单字节、双字节、四字节分段编码方案,具体码位见特性。

GB18030向下兼容ASCII码和GBK编码。

适用范围以及存在问题

GB18030可用于一切处理中文(包括汉字和少数民族文)信息,特别是汉字信息的信息处理产品。

特性

这一标准进行了多次拓展,现在使用的国标标准码就是 GB18030-2005

单字节部分

本标准中,单字节的部分收录了GB/T11383-1989的0x00到0x7F全部128个字符。

双字节部分

本标准中,双字节的部分收录内容如下:

GB 13000.1-1993的全部CJK统一汉字字符。

GB 13000.1-1993的CJK兼容区挑选出来的21个汉字。

GB 13000.1-1993中收录而GB 2312未收录的我国台湾地区使用的图形字符139个。

GB 13000.1-1993收录的其它字符31个。

GB 2312中的非汉字符号。

GB 12345 的竖排标点符号19个。

GB 2312未收录的10个小写罗马数字。

GB 2312未收录的带音调的汉语拼音字母5个以及ɑ 和ɡ。

汉字数字“〇”。

表意文字描述符13个。

对GB 13000.1-1993增补的汉字和部首/构件80个。

双字节编码的欧元符号。

四字节部分

本标准的四字节的部分,收录了上述双字节字符之外的,GB 13000的CJK统一汉字扩充A、CJK统一汉字扩充B和已经在GB13000中编码的我国少数民族文字的字符。

GB18030-2005最主要的变化是增加了CJK统一汉字扩充B。它还去掉了单字节编码的欧元符号0x80)。

GB18030有1611668个码位,在GB18030-2005中定义了76556个字符。随着我国汉字整理和编码研究工作的不断深入,以及国际标准ISO/IEC 10646的不断发展,GB18030所收录的字符将在新版本中增加。

ANSI 编码

简介

(American National Standards Institute) 美国国家标准学会的缩写

针对汉字的编码,不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、Big5、Shift_JIS 等各自的编码标准。这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸编码方式,称为ANSI 编码。

例如:在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文操作系统中,ANSI编码代表Big5编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。

Unicode与UCS

简介

到了全球互联网时代,不同国家,不同地区需要进行交互,这时候由于各自编码标准都不一样,彼此之间都是乱码,无法良好的沟通交流,于是这时候ISO组织与统一码联盟分别推出了UCS(Universal Multiple-Octet Coded Character Set)与Unicode。后来,两者意识到没有必要用两套字符集,于是进行了一次整合,到了Unicode2.0时代,Nnicode的编码和UCS的编码都基本一致(所以后续为了简便会同意用Unicode指代),这时候所有的字符都可以采用同一个字符集,有着相同的编码,可以愉快的进行交流了。

需要注意的是UCS标准有自己的格式,如UCS-2(双字节),UCS-4(四字节)等等 而Unicode也有自己的不同编码实现,如UTF-8,UTF-16,UTF-32等等 其中UTF-16可以认为是UCS-2的拓展,UTF-32可以认为是UCS-4的拓展,而Unicode可以认为是Unicode最终用来制霸互联网的一种编码格式。

Unicode标准

Unicode(统一码、万国码、单一码、标准万国码)编码就是为了表达任意语言的任意字符而设计

在这套系统中: 一个字符代表一个code,不存在二义性,例如U+0041总是代表'A',而且这套标准也会随着需求不断的拓展。

Unicode是一个标准,只规定了某个字符应该对应哪一个code,但是并没有规定这个字符应该用即为字节来存储。规定用几个字节存储字符的是Unicode的不同实现,譬如UTF-8,UTF-16等

Unicode编码的不同实现

UTF-8编码

简介

UTF-8是Unicode的一种实现方式,是一种变长编码,根据不同的Unicode字符,用1到6个字节编码。

UTF-8的字节结构有特殊要求,比如我们说一个汉字的范围是0X4E00到0x9FA5,是指Unicode值,至于放在UTF-8的编码里去就是由三个字节来组织。

编码范围

所有的Unicode码。

适用范围以及存在问题

适用于所有地方,特别是互联网上,现今UTF-8基本已经制霸互联网。

中文中的缺点

UTF-8在中文字符处理时,一般都是3个字节,这样相比GBK,UTF-16等编码,会更浪费空间(但是针对英文又有天然的优势-单字节)

而且因为每个字符使用不同数量的字节编码,所以寻找串中第N个字符是一个O(N)复杂度的操作 — 即,串越长,则需要更多的时间来定位特定的字符。同时,还需要位变换来把字符编码成字节,把字节解码成字符。

特性

变长编码

根据不同的Unicode字符,用1到6个字节编码,而且完全兼容ASCII码

UTF-8是采用变长的编码方式,为1~6个字节,但通常我们只把它看作单字节或三字节的实现,因为其它情况实在少见。UTF-8编码通过多个字节组合的方式来显示,这是计算机处理UTF-8的机制,它是无字节序之分的,并且每个字节都非常有规律

UTF-16编码

简介

Unicode编码中,最常用的字符其实是0-65535,因此针对这点产生了UTF-16方案。

UTF-16将0–65535范围内的字符编码成2个字节,超过这个的用4个字节编码。(因此基本可以认为是双字节的)

UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式直接保存下来。所以UTF-16采用2个字节来存储Unicode。UTF-16也可以表示UCS-4的部分字符,所以UTF-16也采用4个字节来存储Unicode。

UTF16编码是Unicode最直接的实现方式,通常我们在windows上新建文本文件后保存为Unicode编码,其实就是保存为UTF16编码。

编码范围

所有的Unicode码。

适用范围以及存在问题

双字节编码相比UTF-8更利于存储汉字字符。

Tips: JavaScript的内置的实现可以认为是UCS-2(并且它的存储方式为大端序),而UTF-16是UCS-2的拓展。

特性

双字节和四字节编码

由于UTF-16固定是两字节的(UCS-4部分字符4字节),所以无法支持单字节的ASCII码

大端序和小端序

UTF-16和UTF-32都有大端序和小端序问题。

UTF-32编码

简介

UTF-32是Unicode的一种实现方式. UTF32编码使用固定的4个字节来存储。 因此,非常浪费空间,不利于网络传输,所以使用不普遍。

编码范围

所有的Unicode码。

适用范围以及存在问题

不建议使用。

Tips:  HTML5中明确规定禁止使用Utf-32编码。

特性

四字节编码

UTF-32固定使用四个字节来存储。

附录

参考资料

上一篇     下一篇
Lichun Dai

Lichun Dai

程序员,偏前端。会点口琴和吉他。

博客 62 项目 2 随笔 107

GitHub 5sing 知乎 segmentfault 掘金