关于字符编码,最早的概念可能来自于这样的对话:
- “哎呀这个文本是乱码怎么办!”
- “你用UTF-8再打开一次。”
- “咦?好了欸!”
以上只是个开篇的小段子,作为一个依靠代码吃饭的人,在日常的工作和学习之中肯定免不了接触各种各样的编码问题,简单可能是别人发过来的脚本打开是乱码,复杂的可能是web开发中的展示和存储问题,页面展示、信息存储和解读、文件下载和保存甚至于debug看个日志,你都要先设置一下编码格式,否则就要面对一份天书,无从下手。今天就从计算机编码的最开始分析一下这个问题。
ASCII码的诞生
我们都知道计算机使用0和1的两个状态来存储所有信息的,我们把能表示0和1状态的单位成为位(bit),每八位组合在一起,就构成了计算机最基本的存储单位——字节(byte)。而我们常说的KB、MB和GB,和Byte的换算关系是这样的:
1KB=1024B
1MB=1024KB
1GB=1024MB
这个都属于常识问题了,即便你不是专业的程序员,这个换算关系肯定也是知道的。那么ASCII码和字节有什么关系呢?
上个世纪60年代,美国指定了一个字符编码标准,这个字符编码标准使用一个字节来表示一个信息,一个字节有多少种变化呢?这个很好计算:一个字节有8位,每位有2个状态,那么一个字节有2的8次方一共256个状态。在制定好的这个字符编码标准里,前32种状态被定义成控制码,当终端(可能是计算机也可能是打印机之类的硬件设备)接收到前32种状态码中任意一种状态时,都会根据定义好的规则执行相应的动作。比如:
00000000:空字符
00000001:标题开始
00000111:响铃
具体码表,感兴趣的可以参照ASCII中文网给出的码表。
完成了对前32种编码的定义之后,这个标准将英文字母、阿拉伯数字、英文标点符号也使用状态码来表示,这个一直使用到了第127个状态。这个标准,也就是ASCII编码,是计算机最初使用的编码标准。
ASCII码扩展阶段
沿着上面这个标准,美国人很舒服的用了一段时间,但后来当计算机技术可是传播到其他国家的时候,问题出现了。前127个状态里面只包含了英文字母,那不讲英文的国家怎么办呢?编码标准的第一次扩充出现了。
为了在计算机中保存非英语语言的文字,原来一直很清闲的128-255号编码派上了用场,它们开始表示新的字母和符号,这些编码称之为扩展字符集。至此,256个状态被分配完毕,ASCII再也没有新的状态可用了。
通过ASCII的扩展字符集,除英语之外的一些其他语言也可以正常的计算机上存储和使用,解决了当时他们遇到的问题。
GB2312的出现
扩展字符集解决了当时一些国家不能输入的问题,但是,当中国人开始使用计算机的时候,新的问题出现了。汉语跟英语、法语不一样,后两种语言都是使用字母拼成单词来表达意思,在进行存储的时候只需要存储基本字母就可以了,这个量很小。但汉语是通过汉字组合在一起的,常用汉字有6000多个,6000多个汉字如果使用原有的编码标准,那是无论如何也存储不了了。
劳动人民给出的解决方案是这样的:
- 取消127号之后的编码定义,也就是取消扩展字符集;
- 小于127号的字符认为是ASCII码的原有定义
- 大于127号的字符,两个连在一起表示一个汉字或者符号,第一个byte是高字节(0xA1-0xF7),第二个byte是低字节(0xA1-0xFE)
同时,在这个解决方案里,劳动人民不仅放入了汉字,还把什么罗马希腊字母,日本假名都编进去了。全角字符也是在这个时候出现的,位于127号以前的数字标点字母是半角,两字节的字符就是全角字符。这套标准就是GB2312中文标准,也是基于ASCII的一套扩展。
GBK和GB18030
看到这里你是不是在想,不是已经扩充过了吗,咋还有?这是因为汉字,实在是太多了,GB2312只收录了常用的6000多个汉字,在实际使用中,人们就发现有一些生僻字打不出来啊,还是没法用。在这种情况下,只能对现有字符集进一步扩展。GBK就是在GB2312的基础上增加了20000个左右汉子(包括繁体字),GB18030就是在GBK的基础上增加了少数民族用字而来的。
统一标准的出现——UNICODE
相比看到这里你能够猜到随着计算机在全世界范围内的普及,各种编码标准如同雨后春笋一样纷纷出现。一般来讲,百家争鸣是好事儿,但实际上呢,这给计算机的使用者带来极大的麻烦。为了能够正常显示不同的文字,必须在使用的计算机中安装不同的字符编码,否则就不能正确的显示信息。
为了解决这个问题,ISO国际标准化组织给出了一个简单的解决方案,废除所有的地区性编码方案,制定一个包括了地球上全部文字、符号、字母的编码,这个方案就是一统天下的UNICODE了。
UNICODE中,所有的字符都以两个字节表示,对于ASCII中的已经存在的字符,用补0的方法将其长度扩展为16位,其他的语言则全部使用16编码的模式。
UTF-8和UTF-16
说到UNICODE,问题似乎就全部解决了,那UTF-8和UTF-16又是什么呢?上面有一个小细节,那就是UNICODE是标准统一的字符集,但并不包括存储方案。UTF-8和UTF-16就是将UNICODE数字编码转换到程序数据的编码方案,或者说,我们可以认为UTF-8和UTF-16是UNICODE的一种实现方式,这样就好理解多了。比如活字印刷术,UNICODE是铅字,UTF-8就是排版和印刷的工人。
最后,写完了给自己鼓鼓掌。在把这篇文章写完之前,我自己对于编码的了解也只是知其然不知所以然,在遇到?那个问题之后,才决定抽时间把这些都整理一下。拖拖拉拉到了今天才写完,也算有所收获吧。
附上版权声明:
原作者:Vi_error,博客地址:Vi_error.nextval
转载请保持署名和注明原地址