ACSCII,GBK,Unicode,UTF-8这些名词都跟编码有关系,究竟是什么关系呢,看网上的确有很多解释,也很详尽,不过我觉得还是很有必要把我自己学习的历程记录下来。

ACSCII码

在计算机的世界是只有0和1,数据的计算,传输,保存等过程都是通过0和1,可以说0和1是组成计算机的元素。
对于最早使用计算机的美国人,为了记录a,b,c,d等这些字母,1,2,3等还有其他的符号,共收集了128个(2的7次方),于是为了更好记录就有了ASCII(American Standard Code for Information Interchange,美国信息互换标准代码,ASCⅡ)码,可以看下每个符号对应的ACSCII码。



这对于使用英语的人已经满足了人的大部分需求,因为有了26个字母,有了数字和各种控制符,就可以玩转计算机。但是,随着计算机传入我们国家,ACSCII码肯定不够用,怎么办?

GB 2312以及GBK

早先的ASCII编码字符集由于受到单字节的限制。随着国内计算机的发展,中国国家标准总局发布了一套《信息交换用汉字编码字符集》的国家标准,其标准号就是GB 2312。这个字符集共收入汉字6763个和非汉字图形字符682个,同时,收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。整个字符集分成94个区,每区有94个位。,具体的编码表可以参照GB2312简体中文编码表

第03区

可以通过上面的第03区的编码表看到每个区位对应一个字符,因此可用所在的区和位来对汉字进行两字节编码。

实际上,GB2312收录的只是常用汉字,对于一些生僻字,繁体字,GB2312依然不够,于是又有了后来的GBK字符集以及编码规范,但GBK是兼容GB2312的。

相信GBK和GB2312也是大最常见的字符集,但是这只是对国内的计算机,对于一些希腊字母以及其他国外的文字,怎么通信呢?这就需要一个国际化的字符集或者标准,于是unicode编码就在这种情况下诞生啦。

Unicode字符集

ACSCII码满足不了非英语系的语言后,出现了各种各样的编码格式如简体汉字的GBK字符集,台湾繁体的Big5字符集(大五码),日语的JIS等等各自为战,这对于国际化来说是一个很纠结的问题,打开一个网页若是不知道是什么编码就可能是一篇乱码的火星文。于是有人提出了搞一个国际化的标准Unicode。 Unicode最初我们常见肯定是两个字节的,也就是说16位,如汉字的“李”对应的Unicode就是674E,这样对于大部分的非英语系的文字是没有问题的。但是,对于之前说过的ACSCII码采用两个字节的太浪费.若是ACSCII码若是采用两个字节的话,第一个字节的都是0填充,而低位才是真正有效的,这杨来看,对于经常使用英文字母(包含在ACSCII码)的歪果仁来说,这个Unicode一点都不高效。所以怎么高效传送Unicode呢?也是出现了后来各式各样的编码方式:UTF-8,UTF-16,UTF-32,但是我们常用的可能就是UTF-8,UTF-16。

那么怎么用utf-16来表示一个字符呢,需要先讲下具体的规则。
UTF-16是目前各大操作系统和框架支持比较好的编码方式,可以认为它是双字节的,如上文所述,采用16位存储的方式。

UTF-8则是将一些比较长的字符,按照一定的规则分成若干个八位来存储,同时兼容ACSCII码
对于只需要7位都可以存储的:
0XXXXXXX
若是超过7位的,则是需要在高位来存储表示来表示整个编码的长度:
如110XXXXX 10XXXXXX 两个字节,一个字节是一个单元,其中其中110表示这个编码串的长度是2
,10是低位单元的前缀。所以有效字符应该是去掉110和后面的10,
1110XXXX 10XXXXXX 10XXXXXX 三个字节,110表示三个字节,后面的两个10是低位单元的前缀。

如李的UTF-8编码:

1
2
3
4
# 李 16进制
E6 9D 8E
# 李 16进制
11100110 10011101 10001110

当我们把110 10去掉后,发现其实他就是UTF-16对应的674E。UTF-8转UTF-16,其实是就是将每个单元的前缀(110,10)去掉,后不够一个字节的,在第一个字节的高位用0填充。
如汉字李的UTF-8编码:

  1. 由于第一个单元的高位含有三个1,可知和紧随其后的两个字节是一个完整的字
  2. 去掉1110 10得到0110 011101 001110,正好16位,得到的结果为:674E`

所以当我们需要自己编码或者转码时,只需要参照UTF-8的学习方法即可,谨以此文,抛砖引玉。