从ASCII到UTF-8——字符集到底是什么?

这世界上大概有100万个字符,平均每个人一生接触的字符数在6k左右,那么问题来了,如何让计算机来存下所有的字符。

ASCII

计算机诞生于美国,起初用的是真空管的电位高低来表示0和1,8个真空管为一组,由此组成了计算机内的单位——Byte字节,大小为8个bit。

美国人一生只需要识别26个字母就够了。于是,他们用半个字节就足以表示自己所能识别的字符。这就是ASCII字符集,范围为0-127.

其中,0x20以下为控制字符,不可显示。比如,0x10表示换行,0x07表示发声。另外还有个特殊的控制字符,0x7f表示删除。

0x30表示数字0;0x41表示字母A;0x61表示字母a。

这个字符集占的空间小,又足以满足日常需求,美国人很满意。

ASCII扩展

欧洲国家进口计算机后,也有了在计算机上显示自己的常用字符的要求,于是乎,就想着对ASCII进行扩展。

你美国人不是才用了半个字节吗,那好,剩下的半个字节由我们来定义。

于是乎,0x80 - 0xff的定义就被填充成了希腊字母,罗马字母等符号。

此时,编码依旧控制在8位以内,相安无事。

GB2312

古老的中国,终于也开始接触计算机。它博大精深的文化,怕是ASCII编码的制定者所始料未及的。

美国人想到中国的键盘,怎么着至少也得两千多个键吧。

呵呵,区区一个字节,256个坑位,怎么填的下我博大精深数千汉字字符呢。

于是,强大的天朝发布了自己的字符编码标准——GB2312.

思想很简单,如果一个字符值为127及以下,那它就是一个单字节字符,和ASCII兼容; 如果一个字符值为127以上,那它和后面的那个字符组成一个汉字。(同时,后面那个字符也一定是127以上的)

通过这个方式,我们扩展出来了7000+的简体汉字,同时还把日本假名,罗马希腊字母,数学符号也容纳了进来。

同时还产生了一个新的概念,全角字符:ASCII码里本身有的字符,也被我们扩展成了双字节字符。为了区分,前者称为半角字符,后者称为全角字符。

至此,中文也可以在计算机上表示了。

GBK

还是一个中华文化博大精深的问题,7000个简体汉字并不能把汉字穷举了,一些生僻字并不包含在GB2312里。

GB2312表示,我可能还可以抢救一下,我还有另一半的潜力没有发挥呢!

这另一半的潜力就是,第二个字节的0x00 - 0x7f部分。这部分空出来,是由于GB2312表示汉字时,要求两个字节都是在0x80 - 0xff范围内的。

填上这部分的空档之后,再生僻的字也被表示出来了,同时,我们还考虑到港澳台同胞的感受,包含了繁体字,一共大概增加了20k的汉字和符号。

从今以后,再也不许有人跟我说在计算机里有打不出来的汉字~

Unicode

然而,我们做出来的GBK,并不被对岸承认。因为对岸并没有和我们共建这个标准。 随着时间的推移,互联网的兴起,不止海峡两岸,全世界范围内共建一个字符集的呼声越来越高。

这个标准,只能有一个机构可以做,那就是ISO(我对这个组织的印象是它曾经弄出来了一个教科书级别的网络七层模型,也仅限于教科书使用)。 ISO作为一个类似《圣经》中创世纪的角色,于是说了一句“要有Unicode字符集”。 于是,就有了Unicode字符集。

Unicode,统一了所有地区的字符,且还在不断扩充中。所有地区的字符,都被用两个字节来表示。与前面提到的GBK等不同的是,Unicode并不兼容ASCII。它要求ASCII字符在高8位补0,强行把ASCII码用两个字节来表示。

到这里,世界在Unicode的驱动下,似乎要趋于大同了。

UTF-8

叮咚~ISO的门铃响了,是美国人啦~

回到ASCII的创始那一段,美国人用的最多的,还是26个字母,一个字节可以表示完的字符集,非要用我用两个字节来表示,我山姆大叔今天就是要逆你Unicode的天。你知不知道你让我的网络流量和硬盘存储空间都翻倍啦?

加上一些只认ASCII码的老系统,根本就无法在Unicode环境工作了。

这个时候,就需要一个折中的方案出来了。既兼容ASCII,不造成空间浪费,又能像Unicode那样,囊括四海之内的字符。

这个时候,UTF-8编码被提出来了。

前面说的都是字符集,UTF-8却是一种编码方式,因为它并不是去做字符集的事情,而是为的便于Unicode码的传输和存储而生的。

与其他的编码方式(如哈夫曼编码)的思想一致,UTF-8的原则就是,使用不定长字节(1-6字节)来表达一个字符,使用频率越高的字符,字节数越少。这样就能最大程度上节约空间。具体的编码方式如下:

单字节字符:
    以0开头,后面7位表示字符,事实上,UTF-8的单字节字符就是ASCII字符,完美兼容;
n字节字符:
    第一个字节的前n位为1,第n+1位为0。读到此字节时,可以方便的知道后续多少字节是用来表示一个字符;
    其余字节,以10开头。
复制代码
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和Unicode是一一对应的,对于常用汉字,基本上都是占用3个字节,生僻汉字可能占用到6个字节。对于GB2312和GBK来讲,UTF-8无疑造成了浪费,所以,UTF-8可以说是对英文友好,但对中文不友好的一种编码方式。所以在中文界,GB2312与GBK依旧有自己的市场。

总结

简单来说:
美国人为了表示日常用的字符,制定了ASCII。用一个字节来表达字符;
欧洲人为了表示日常用的字符,扩充了ASCII。加入ASCII扩展字符;用一个字节来表达字符;
中国人为了表示常用简体汉字,制定了GB2312。用两个字节来表达字符;
中国人为了表示生僻汉字和繁体字,扩充GB2312为GBK。用两个字节来表达字符;
ISO为了统一全世界的字符,制定了Unicode。用两个字节来表达字符;
为的便于Unicode的传输和存储,UTF-8编码方式被制定出来。使用1-6个不定字节来表达字符。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值