摘要:
本文主要讲解字符集和字符编码的一些概念,通常我们所说的字符集其实指的包含了字符编码集 字符编码。但字符集有时候有时候又只是字符编码集的简称,具体语义根据上下文判断理解就行,也不是必须分的很清楚。
起源:
为什么会出现字符集和字符编码呢?其实追根到底就是因为计算机不能直接存储字母,数字,图片,符号等,计算机只能处理数字,计算机能处理和工作的唯一单位是"比特位(bit)",一个比特位只有 0 和 1。如果要处理文本,就必须先把文本转换为数字才能处理。但是,问题来了,计算机拿到一堆数字,它怎么知道是什么意思呢?退一步讲,计算机把这些数字处理过后的结果数字,我们又怎么能知道是什么意思呢?
编码解码:
上面说到,我们要处理文本就得把文本转成计算机能识别的bit,利用比特位序列来代表字母,数字,图片,符号等,我们就需要一个存储规则,不同的比特序列代表不同的字符,这就是所谓的"编码"。反之,将存储在计算机中的比特位序列(或者叫二进制序列)解析显示出来成对应的字母,数字,图片和符号,称为"解码"。
术语:
首先我们需要了解一些术语
字符集合(Character set):是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等,简单理解就是一个字库,与计算机以及编码无关,通俗的理解在老冯发明计算机前我们就有字符集合这个概念了。
字符编码集(Coded character set):是一组字符对应的编码(即数字),为字符集合中的每一个字符给予一个数字,如 Unicode 为(全世界)每一个字符分配一个唯一的码点与之一一对应。
字符编码(Character Encoding):简单理解就是一个映射关系,一个编码规则。将字符集对应的码点映射为一个个二进制序列,从而使得计算机可以存储和处理。常见的编码方式有 ASCII 编码、ISO-8859-1(不支持中文)、GBK、GB2312(中国编码,支持中文)、UTF-8 等等,详情见表 1。
字符集(Charset):包括字符编码集和字符编码,如 ASCII 字符集、ISO-8859-X、GB2312 字符集(简中)、BIG5 字符集(繁中)、GB18030 字符集、Shift-JIS 等,即下文中提到的字符集。
表 1. 常见字符集和对应编码方式
字符集 | 编码 | 详解 |
---|---|---|
ASCII | ASCII 编码 | ASCII字符集:主要包括控制字符(回车键、退格、换行键等);可显示字符(英文大小写字符、阿拉伯数字和西文符号。ASCII 编码:用一个字节的低 7 位表示,0~31 是控制字符如换行回车删除等;32~126 是打印字符;ASCII的最大缺点是只能解决了部分西欧语言的显示问题,但对更多其他语言依然无能为力。 |
ISO-8859-X(常用的 ISO-8859-1) | ISO-8859-1 编码ISO-8859-2 编码…ISO-8859-15 编码 | ISO-8859-X 字符集:扩展的 ASCII 字符集,包括 ISO-8859-1 ~ ISO-8859-15,涵盖了大多数西欧语言字符和希腊语。ISO-8859-1 编码:用 8 位表示一个字符,总共能表示 256 个字符,但还是单字节编码,不能对双字节如中日韩等进行编码。 |
GBXXXX | GB2312 编码 | GB2312 编码 :它的全称是《信息交换用汉字编码字符集 基本集》,它是双字节编码,每个汉字及符号以两个字节来表示。第一个字节称为"高位字节"(也称"区字节)",第二个字节称为"低位字节"(也称"位字节")。总的编码范围是 A1-F7,其中从 A1-A9 是符号区,总共包含 682 个符号,从 B0-F7 是汉字区,它所收录的汉字已经覆盖中国大陆 99.75%的使用频率。对于人名、古汉语等方面出现的罕用字,GB2312 不能处理,这导致了后来GBK及GB 18030汉字字符集的出现。 |
GBK 编码 | GBK 编码:全称叫《汉字内码扩展规范》,是在 GB2312-80 标准基础上的内码扩展规范,使用了双字节编码方案,其编码范围从 8140 至 FEFE(剔除 xx7F),共 23940 个码位,共收录了 21003 个汉字,完全兼容 GB2312-80 标准,支持国际标准 ISO/IEC10646-1 和国家标准 GB13000-1 中的全部中日韩汉字,并包含了 BIG5 编码中的所有汉字。 | |
GB18030 编码 | GB18030-2005《信息技术中文编码字符集》是我国自主研制的以汉字为主并包含多种我国少数民族文字(如藏、蒙古、傣、彝、朝鲜、维吾尔文等)的超大型中文编码字符集强制性标准,其中收入汉字 70000 余个,解决了中文、日文、朝鲜语等的编码,兼容 GBK。采用变长字节表示即单字节、双字节和四字节三种方式对字符编码。可表示27484个文字 | |
Big5 | Big5 编码 | Big5 编码:又称为大五码或五大码,适用于台湾、香港地区的一个繁体字编码方案。使用了双八码存储方法,以两个字节来安放一个字,第一个字节称为"高位字节",第二个字节称为"低位字节。 |
Unicode | UTF-8 | UTF-8:采用变长字节 (1 ASCII, 2 希腊字母, 3 汉字, 4 平面符号) 表示,在网络传输中即使错了一个字节,不影响其他字节;存储效率比较高,适用于拉丁字符较多的场合以节省空间,UTF-8 没有字节顺序问题,所以 UTF-8 适合传输和通信。 |
UTF-16 | UTF-16:从先前的固定宽度的 16 位编码(UCS-2)发展而来的,能够对 Unicode 的所有 1,112,064 个有效 code point 进行编码。其编码方式是可变长度的,因为 code point 是用一个或两个 16 位代码单元编码的。在 UTF-16 文件的开头,会放置一个 U FEFF 字符作为 Byte Order Mark(BOM):UTF-16LE(小端序)以 FF FE 代表,UTF-16BE(大端序)以 FE FF 代表,以显示这个文字档案是以 UTF-16 编码。UTF-16 比起 UTF-8,好处在于大部分字符都以固定长度的字节 (2 字节) 储存,但 UTF-16 却无法兼容于 ASCII 编码,实际使用也比较少。 | |
UTF-32 | UTF-32 (或 UCS-4):对每一个 Unicode 码点使用 4 字节进行编码,其它的 Unicode 编码方式则使用不定长度编码。就空间而言,UTF-32 是非常没有效率的。尤其非基本多文种平面的字符在大部分文件中通常很罕见,以致于它们通常被认为不存在占用空间大小的讨论,使得 UTF-32 通常会是其它编码的二到四倍。虽然每一个码位使用固定长度的字节看似方便,它并不如其它 Unicode 编码使用得广泛。 |
由此我们就明白了为什么中文默认使用 GB1832 而不使用 UTF-8?因为 GB1832 对绝大多数中文采用双字节编码,而 UTF-8 要用三字节,GB11832 大大节省了存储空间。GB2312、GBK、UTF-8、UTF-16 这几种格式都可以用来对汉字进行编码,在实际应用中具体选择哪种编码方式,需要根据实际应用场景,当前的应用场景是编码效率重要还是减少存储空间重要。
UTF-8可变长度字符编码:
UTF-8是可变长度的字符编码,能够使用1~4个8位字节对编码表中的有效代码点进行编码,它被设计成向后兼容,Unicode的前128个字符与ASCII一一对应,所以有效的ASCII文本也是有效的UTF-8编码。UTF-8是互联网上使用最广的字符编码规则,占所有网页的92%左右。
UTF-8中的8意思是以8位为一个编码单元进行的编码,同理UTF-16就是以16位为一个单元进行编码。为了更好的理解后面所介绍的内容,这里介绍一下UTF-8的编码规则。
根据上图,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。
其他常见术语:
ANSI 编码:各个国家和地区独立制定的既兼容 ASCII 编码又彼此之间不兼容的字符编码,微软统称为 ANSI 编码,又称为"MBCS(Muilti-Bytes Charecter Set,多字节字符集)"。在 Windows 系统中,ANSI 编码一般代表系统默认的编码方式,并且不是确定的某一种特定编码方式,比如在英文 Windows 操作系统中,ANSI 指的是 ISO-8859-1;简体中文操作系统中 ANSI 编码默认指的是 GB 系列编码(GB2312、GBK、GB18030)等;在繁体中文操作系统中 ANSI 编码默认指的是 BIG5;在日文操作系统中 ANSI 编码默认指的是 Shift JIS 等等,并且默认的 ANSI 编码可以通过设置系统 Locale 更改。
UCS(Universal Character Set):称作通用字符集,是由 ISO 制定的 ISO 10646(或称 ISO/IEC 10646)标准所定义的标准字符集。包括了其他所有字符集。它保证了与其他字符集的双向兼容,即,如果你将任何文本字符串翻译到 UCS 格式,然后再翻译回原编码,你不会丢失任何信息。
UTF(UCS transform format/Unicode transformation format): UCS 转换格式/Unicode 转换格式。
等等!我有问题:
UCS跟Unicode咋回事?有些懵懵的。
别急,让我们一起来回顾下历史,话说。。。
Unicode与UCS(ISO 10646)的结拜历史:
(1) 国际标准化组织(ISO),他们于1984年创建ISO/IEC JTC1/SC2/WG2工作组,试图制定一份“通用字符集”(Universal Character Set,简称UCS),并最终制定了ISO 10646标准。
(2) 统一码联盟,他们由Xerox、Apple等软件制造商于1988年组成,并且开发了Unicode标准(The Unicode Standard,这个前缀Uni很牛逼哦---Unique, Universal, and Uniform)。
然后重点来了,两家拜把子做兄弟了!
1991年前后,两个项目的参与者都认识到,世界不需要两个不兼容的字符集。于是,它们开始合并双方的工作成果,并为创立一个单一编码表而协同工作。从Unicode 2.0开始,Unicode采用了与ISO 10646-1相同的字库和字码;ISO也承诺,ISO 10646将不会替超出U 10FFFF的UCS-4编码赋值,以使得两者保持一致。两个项目仍都独立存在,并独立地公布各自的标准。不过由于Unicode这一名字比较好记,因而它使用更为广泛。
你可以简单的这么认为:现在这两个集合的key-value是统一的了。
当然,虽然统一了,但是各自家的孩子的名字还是不一样的嘛。
UTF-32与UCS-4:
在Unicode与ISO 10646合并之前,ISO 10646标准为“通用字符集”(UCS)定义了一种31位的编码形式(即UCS-4),其编码固定占用4个字节,编码空间为0x00000000~0x7FFFFFFF(可以编码20多亿个字符)。
UCS-4有20多亿个编码空间,但实际使用范围并不超过0x10FFFF,并且为了兼容Unicode标准,ISO也承诺将不会为超出0x10FFFF的UCS-4编码赋值。由此UTF-32编码被提出来了,它的编码值与UCS-4相同,只不过其编码空间被限定在了0~0x10FFFF之间。因此也可以说:UTF-32是UCS-4的一个子集。
UTF-16与UCS-2:
除了UCS-4,ISO 10646标准为“通用字符集”(UCS)定义了一种16位的编码形式(即UCS-2),其编码固定占用2个字节,它包含65536个编码空间(可以为全世界最常用的63K字符编码,为了兼容Unicode,0xD800-0xDFFF之间的码位未使用)。例:“汉”的UCS-2编码为6C49。
但俩个字节并不足以正真地“一统江湖”,于是UTF-16诞生了,与UCS-2一样,它使用两个字节为全世界最常用的63K字符编码,不同的是,它使用4个字节对不常用的字符进行编码。UTF-16属于变长编码。