码表
理解
计算机保存的是二进制代码,使用码表使每个二进制代码代替十进制数。这张表中规定了字符和二进制的映射关系。计算机存储字符时将字符查询码表,然后存储对应的二进制。计算机取出字符时将二进制查询码表,然后转换成对应的字符显示。
ASCII
美国码表,码表中只有英文大小写字母、数字、美式标点符号等。每个字符占用1个字节,所有字符映射的二进制都为正数,因此有128个字符映射关系。
GBK/GB18030
GBK 编码是使用双字节来表示的,即不论中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定成1。GBK包含全部中文字符,是国家编码,通用性比UTF8差,不过UTF8占用的数据库比GBK大。
Unicode
Unicode 是一个很大的集合,是十六进制的,现在的规模可以容纳 100 多万个符号。每个符号的编码都不一样,比如,U+0639表示阿拉伯字母Ain,U+0041表示英语的大写字母A,U+4E25表示汉字“严”。
Unicide 是一个符号集,规定了符号的二进制代码,却没有规定如何存储二进制代码。那么如何区别 unicode 和 ascii 呢?计算机怎么知道三个字节表示一个符号,而不是三个符号?于是就衍生了 UTF-8。
UTF-8
UTF-8 是 unicode 的一种实现方式之一。它是一种可变长度字符集,每个字符编码最多四个字节。
UTF-8的编码规则很简单,只有二条:
对于单字节的符号,字节的第一位(字节的最高位)设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的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 |
因此对于英语字母,使用 utf-8 与 ascii 是一样的。
UTF-8 存储的字符,除了第一个字节外,其余字节的头两个比特都是以”10”开始,使文字处理器能够较快地找出每个字符的开始位置。
举个栗子
例如“严”,unicode 字符是 4E25(100111000100101)
,4e25
在第三行范围,因此需要三个字节,将二进制码以此替换掉上面的 x,得到最终的 utf-8 编码为:11100100 10111000 10100101
。转换成十六进制就是E4B8A5
虽然 utf-8 具有良好的国际通用性,但是 utf-8 中的中文使用三个字节来编码,比 gbk 多占用了 50% 的存储空间。下面来介绍 gbk 编码方式。
Base64
是基于 64 个可打印的字符来表示二进制的数据的一种方法,用于解决中文、日文等文字无法被服务器或网关有效处理。
64 个字符:A~Z、a~z、0~9、+、/,还会使用 = 做填充字符
转换步骤
- 三个字节分一组,每个字节 8 位,总共 24 位
- 将 24 位每 6 位分一组,共分为四组(如果不足6位则补0,如果 6 位全是空的,则使用 = 号代替)
- 每组前面添加 2 个 0,变为 8 位二进制位,共四个字节
- 使用每个字节的值作索引,获得对应的值