对常用编码的全面理解

众所周知,计算机里的所有信息都表示为一个二进制字符串,而编码的作用就是建立一个人类字符和二进制位之间的映射,来方便人与计算机之间、人与人之间的信息交流。

ASCII码:

American Standard Code for Information Interchange,美国信息互换标准代码。

上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为ASCII码,一直沿用至今。

编码规则:

ASCII码一共规定了128个字符的编码,比如空格“SPACE”是32(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括32个不能打印出来的控制符号),只占用了一个字节的后面7位,最前面的1位统一规定为0。

ASCII码用了1个字节,1个字节可以表示256种状态,但ASCII码只用了128种,也就是一个字节的后七位,最前面的1位都是0

各个国家自己的编码:

由于ASCII码只有规定了128个字符,没有考虑到其他国家的字符,比如中文字符,所以不同国家继承ASCII码建立了自己的编码。

比如中文字符编码:

我们不客气地把那些127号之后的奇异符号们直接取消掉, 规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127号以下的那些就叫”半角”字符了。中国人民看到这样很不错,于是就把这种汉字方案叫做 “GB2312“。GB2312 是对 ASCII 的中文扩展。

后来发现不够用:

于是我们不得不继续把GB2312 没有用到的码位找出来老实不客气地用上。后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK 标准,GBK包括了GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。 后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK扩成了 GB18030

这种中文字符编码方式被统称为“DBCS“(Double Byte Charecter Set 双字节字符集),也是为什么我们常说的,中文字符编码长度是英文的两倍。

Unicode字符集:

每个国家都有自己的一套编码,非常不利于国际交流,所以ISO(国际标准化组织)推出了一个包含地球上所有字符的编码集——”Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “Unicode“。

Unicode编码集虽然规定了字符该用哪个二进制串表示,但是有的字符只需要一个字节,而有的字符却需要多达四个字节,如果都用4个字节来表示一个字符的话,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。

Unicode编码规则:

Unicode编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码。(这种情况下如果一个字符的unicode超过2个字节就存不下了)

UTF-8:

互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种Unicode的实现方式。UTF(UCS Transfer Format)即Unicode字符集的编码规则。

UTF-8 与 Unicode区别:

  • Unicode 是 「字符集」
  • UTF-8 是 「编码规则」

字符集:为每一个字符分配一个唯一的ID(码位/码点/Code Point) ;
编码规则:将码位转换为字节序列的规则(编码/解码 => 加密/解密)。

UTF-8的编码规则:

UTF-8是一种变长字节编码方式。最小编码单位(code unit)为一个字节。一个字节的前1-3个bit为描述性部分,后面为实际序号部分。

  1. 对于单字节字符,占用一个字节空间。0之后的所有部分(7个bit)代表Unicode中的序号。因此对于英文字母,UTF-8编码和ASCII码是相同的。
  2. 对于n字节字符,第一个字节的前n为都为1,第n+1为0,后面字节的前两位上为10。剩下没有提及的二进制位为这个符号的unicode码。
Unicode符号范围「十六进制」 UTF-8编码「二进制」
0000 0000-0000 007F 0xxxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx

综上: 如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前占用多少个字节。

“严”的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此“严”的UTF-8编码需要三个字节,即格式是“1110xxxx 10xxxxxx 10xxxxxx”。然后,从“严”的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,“严”的UTF-8编码是“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。

Little endian和Big endian:

之前提到了Unicode一般使用UCS-2编码方式,有两种格式:Little endian和Big endian。

以汉字”严“为例,Unicode码是4E25,需要用两个字节存储,一个字节是4E,另一个字节是25。存储的时候:

  • 4E在前,25在后,就是Big endian方式;
  • 25在前,4E在后,就是Little endian方式。

计算机怎么知道某一个文件到底采用哪一种方式编码?
Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做”零宽度非换行空格“(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。
如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。

Base64:

Base64是一种基于64个可打印的字符来标识二进制数据的标识方法。可打印的字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印的符号在不同系统中而不同。

在MIME格式的的电子邮件中,另外两个符号为加号+和斜杠/,等号=用来做后缀用途。

编码转换方式

  1. 将每三个字节作为一组,一共24个二进制位。
  2. 将这24个二进制位分为4组,每个组有6个二进制位。
  3. 在每组前面加两个00,扩展成32个二进制位,及四个字节。
  4. 然后根据下表得到扩展后的每个字节的编号,这就是Base64的编码值。
索引 对应字符 索引 对应字符 索引 对应字符 索引 对应字符
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w
15 P 32 g 49 x
16 Q 33 h 50 y

Base64字符标中的字符原本用6bit就可以表示,现在前面添加2个0,变为8bit,导致Base64编码后的文本大小比原文大约三分之一。

Base64编码举例.png

位数不足3位处理

  1. 二位的情况:两个字节共16个二进制位,按照上面方式分组,每6个一组,则第三组缺少2位,用0补齐。如”Ma”可以转换为三组00010011、00010110、00010000,对应的Base64值分别为T、W、E,再补上一个”=”号,因此”Ma”的Base64编码为”TWE=”;

  2. 一位的情况:一字节共8个二进制位,按照上面方式分组,每6个一组,则第二组缺少4位,用0补齐。如”M”可以转换为00010011、00010000,对应的Base64位的值分别为:T、Q,再补上两个”=”号,因此”M”的Base64编码就是”TQ==”;

注意事项

  • 大多数编码都是由字符串转换为二进制的过程,而Base64的编码则是从二进制转为字符串。
  • Base64主要用在传输,存储,表示二进制领域,不能算得上加密,只是无法直接看到铭文。
  • 中文有很多编码(比如:UTF-8、GB2312、GBK等),不同的编码对应的Base64编码结果不一样。

最后一首诗总结一下:

手持两把锟斤拷

口中疾呼烫烫烫

脚踏千朵屯屯屯

笑看万物锘锘锘

参考资料:

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享