目录
- 1、基础知识
- 2、ASCII编码
- 3、编码格式
- 4、多字节字符集(MBCS)和中文字符集
- 5、ANSI 标准、国家标准、 ISO 标准
- 6、Unicode 编码
- 7、 UTF-8编码
1、基础知识
👉字符:是各种文字和符号的总称,包括各个国家的文字,标点符号,图形符号,数字等。
👉字符集:字符集是多个符号的集合,每个字符集包含的字符个数不同。
👉字符编码:字符集只是规定了有哪些字符,而最终决定采用哪些字符,每一个字符用多少字节表示等问题,则是由编码来决定的。计算机要准确的处理各种字符集文字,需要进行字符编码,以便计算机能够识别和存储各种文字。
2、ASCII编码
上个世纪60年代, 美国制定了一套字符编码, 对英语字符与二进制位之间的关系, 做了统一规定,这被称为ASCII码。
那时候的字符编解码系统非常简单,就是简单的查表过程。例如将字符序列编码为二进制流写入存储设备,只需要在 ASCII 字符集中依次找到字符对应的字节,然后直接将该字节写入存储设备即可。解码二进制流的过程也是类似。
ASCII码一共规定了128个字符的编码, 比如空格“SPACE”是32(二进制00100000), 大写的字母A是65(二进制01000001)。 这128个符号(包括32个不能打印出来的控制符号), 只占用了一个字节的后面7位, 最前面的1位统一规定为0。
-
特点
0~31 及 127(共 33 个)是控制字符或通信专用字符(其余为可显示字符),如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BS(退格)32~126(共 95 个)是字符(32 是空格),其中 48~57 为 0 到 9 十个阿拉伯数字。
65~90 为 26 个大写英文字母,97~122 号为 26 个小写英文字母,其余为一些标点符号、运算符号等。
后 128 个称为扩展 ASCII 码。许多基于 x86 的系统都支持使用扩展(或“高”)ASCII。扩展ASCII 码允许将每个字符的第 8 位用于确定附加的 128 个特殊符号字符、外来语字母和图形符号。
-
缺点
不能表示所有字符。
相同的编码表示的字符不一样: 比如, 130在法语编码中代表了é, 在希伯来语编码中却代表了字母Gimel。
-
ASCII码表
3、编码格式
世界上存在着多种编码方式,同一个二进制数字可以被解释成不同的符号。因此,要想打开一个文本文件,就必须知道它的编码方式,否则用错误的编码方式解读,就会出现乱码。
编码的发展历程
4、多字节字符集(MBCS)和中文字符集
📌上面我们提到的字符集都是基于单字节编码,也就是说,一个字节翻译成一个字符。这对于拉丁语系国家来说可能没有什么问题,因为他们通过扩展第8个比特,就可以得到256个字符了,足够用了。
📌但是对于亚洲国家来说, 256 个字符是远远不够用的。因此这些国家的人为了用上电脑,又要保持和 ASCII 字符集的兼容,就发明了多字节编码方式,相应的字符集就称为多字节字符集(Muilti-Bytes Charecter Set)。例如中国使用的就是双字节字符集编码。
📌例如目前最常用的中文字符集 GB2312,涵盖了所有简体字符以及一部分其他字符; GBK(K 代表扩展的意思)则在 GB2312 的基础上加入了对繁体字符等其他非简体字符。这两个字符集的字符都是使用 1-2 个字节来表示。
📌Windows 系统采用 936 代码页来实现对 GBK 字符集的编解码。在解析字节流的时候, 如果遇到字节的最高位是 0 的话,那么就使用 936 代码页中的第 1 张码表进行解码,这就和单字节字符集的编解码方式一致了。 如果遇到字节的最高位是 1 的话,那么就表示需要两个字节值才能对应一个字符。
5、ANSI 标准、国家标准、 ISO 标准
📌不同 ASCII 衍生字符集的出现,让文档交流变得非常困难,因此各种组织都陆续进行了标准化流程。
📌例如美国 ANSI 组织制定了 ANSI 标准字符编码(注意,我们现在通常说到 ANSI 编码,通常指的是平台的默认编码,例如英文操作系统中是 ISO-8859-1,中文系统是 GBK), ISO 组织制定的各种 ISO 标准字符编码,还有各国也会制定一些国家标准字符集,例如中国的 GBK,GB2312 和 GB18030。
📌操作系统在发布的时候,通常会往机器里预装这些标准的字符集还有平台专用的字符集,这样只要你的文档是使用标准字符集编写的,通用性就比较高了。例如你用 GB2312 字符集编写的文档,在中国大陆内的任何机器上都能正确显示。
📌同时,我们也可以在一台机器上阅读多个国家不同语言的文档了,前提是本机必须安装该文档使用的字符集。
6、Unicode 编码
在 Unicode 出现之前,所有的字符集都是和具体编码方案绑定在一起的(即字符集≈编码方式),都是直接将字符和最终字节流绑定死了。
例如 ASCII 编码系统规定使用 7 比特来编码 ASCII 字符集;GB2312 以及 GBK 字符集,限定了使用最多 2 个字节来编码所有字符,并且规定了字节序。这样的编码系统通常用简单的查表,也就是通过代码页就可以直接将字符映射为存储设备上的字节流了。如下图:
虽然通过使用不同字符集,我们可以在一台机器上查阅不同语言的文档,但是我们仍然无法解决一个问题:如果一份文档中含有不同国家的不同语言的字符,那么无法在一份文档中显示所有字符。为了解决这个问题,我们需要一个全人类达成共识的巨大的字符集,这就是 Unicode字符集。
-
Unicode
一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用 Unicode 没有乱码的问题。Unicode 只是定义了一个庞大的、全球通用的字符集,并为每个字符规定了唯一确定的
编号,具体存储成什么样的字节流,取决于字符编码方案。推荐的 Unicode 编码是 UTF-16 和UTF-8。 -
Unicode对比早期编码
早期字符编码、字符集和代码页等概念都是表达同一个意思。例如 GB2312 字符集、GB2312编码,936 代码页,实际上说的是同个东西。对于 Unicode 则不同,Unicode 字符集只是定义了字符的集合和唯一编号,Unicode 编码,
则是对 UTF-8、UCS-2/UTF-16 等具体编码方案的统称而已,并不是具体的编码方案。所以当需要用到字符编码的时候,你可以写 gb2312,codepage936,utf-8,utf-16,但请不要写 Unicode。 -
造成乱码的原因
造成乱码的原因就是因为使用了错误的字符编码去解码字节流,因此当我们在思考任何跟文本显示有关的问题时,请时刻保持清醒:当前使用的字符编码是什么。只有这样,我们才能正确分析和处理乱码问题。 -
Unicode缺点
1、Unicode 只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储:无法区别 Unicode 和 ASCII:计算机无法区分三个字节表示一个符号还是分别表示三个符号
2、另外, 我们知道,英文字母只用一个字节表示就够了,如果unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储空间来说是极大的浪费。
7、 UTF-8编码
UTF-8 是在互联网上使用最广的一种 Unicode 的实现方式。
顾名思义,UTF-8 就是每次 8 个位传输数据,而 UTF-16 就是每次 16 个位
UTF-8 是一种变长的编码方式。它可以使用 1-6 个字节表示一个符号,根据不同的符号而变化字节长度。
它可以使用 1~4 个字节表示一个符号。从 unicode 到 uft-8 并不是直接的对应,而是要过一些算法和规则来转换(即 Uncidoe 字符集
≠UTF-8 编码方式)。
UTF-8的编码规则:
对于单字节的UTF-8编码,该字节的最高位为0,其余7位用来对字符进行编码(等同于ASCII码)。
对于多字节的UTF-8编码,如果编码包含 n 个字节,那么第一个字节的前 n 位为1,第一个字节的第 n+1 位为0,该字节的剩余各位用来对字符进行编码。在第一个字节之后的所有的字节,都是最高两位为"10",其余6位用来对字符进行编码。