【编程基础】—字符编码之二三事

相信大家在写脚本或者平时的测试过程中肯定都碰到过乱码,面对自己不认识的怪异字符,肯定会不知所措。今天这篇文章就带大家看看编码格式的发展历程,让你碰到问题时有思路可循。

编码格式发展史

ASCII

众所周知,世界上第一台计算机是美国人在20世纪40年代发明的,当时确定计算机以二进制(0101)的方式来存储数据,也就是说能在计算机上显示的所有字符:数字、大小写字母、符号等最终都需要转成计算机可识别的二进制。因此,必须建立一套从字符到二进制的对应关系,于是 美国国家标准协会(American National Standard Institution) 就收集了当时美国所使用的所有字符(共128个)。因为一个字节包含8位,共有256种二进制组合(2的8次方),所以单个字节就能覆盖所有的字符,并且单个字节的最高位也用不上,因为后7位就可以表达128个字符。ASCII表于1967年正式发布,共包括33个控制字符和95个可显示字符 。

0000 0000-0001 1111 共33种状态表示特殊的终端控制(例如打印机响铃)(0-33)0011 0000-0011 1010 共10个表示0-9十个数字0100 0001-0101 1010 共26个表示大写字母0110 0001-0111 1010 共26个表示小写字母   外加33个符号(运算符、特殊符号)   一共128个占7位 高位不用直接补0。

上面引入了一些基础概念,我们简单介绍下:

  • 位(bit):计算机中最小单位,用二进制的0/1表示。

  • **字节(byte):**每8位组成一个字节。

  • **字符:**我们平时可见的文字、字母、符号、数字等。

  • **字符集:**多个字符的集合。

  • **编码(encode):**将字符转换成计算机可识别的二进制代码(0/1代码)。

  • **解码(decode):**将计算机表示的0/1编码转换成肉眼可见的字符。

EASCII

随后,计算机传入欧洲,欧洲人发现ASCII无法展示他们自己特有的一些字符(表格符号、计算符号、希腊字母和特殊的拉丁符号)。欧洲人灵光一现:ASCII不是没有用到最高位嘛,正好可以利用起来,于是他们将ASCII编码的高位从0变为1,扩展出128个二进制数(10000000~11111111)。

但是实际使用过程中,由于不同国家的字符略有不同,因此有可能同一个二进制数字,但是代表的字符却是不同的, 比如,1000 0010在法语编码中代表了é,在希伯来语编码中却代表了字母Gimel (?),在俄语编码中又会代表另一个符号 。不过编码的0-127是和ASCII完全一致的,唯一有区别的是后面128-255之间的字符不同。这就是EASCII,它完全兼容ASCII。

GB2312

再往后,计算机被引入到亚洲,中华文化博大精深,汉字共包含了古文、现代文字等近十万个文字,就算只考虑我们常用字也有6000多个汉字,所以ASCII肯定是没办法满足需求了。于是,在1981年,国家标准化管理委员会正式制定了 中华人民共和国国家标准简体中文字符集 ,被称之为GB2312。

它共包含7445个字符,6763个汉字和682个其他字符(拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母) ,每个汉字及符号都用两个字节来存储。

BIG5

GB2312是简体中文字符集,但是中国的港澳台同胞们使用的却是繁体字,于是在1984年,中国又联合部分台湾的厂商,一起推出了BIG5编码,它共收录13,060个汉字及441个符号,也采用两个字节来存储字符。

Unicode

随着计算机的普及和发展,越来越多的国家希望自己的文字可以显示在计算机上,于是他们就开始制定自己的编码格式。但是这样带来的后果是,在自己国家电脑上写的好好的一份文件,copy到其他国家的电脑上就完全变成乱码,这挺可怕的,每个国家都活在自己的小世界里,没办法跟其他国家的人交流。

于是国际标准化组织(ISO)及国际电工委员会(IEC)于1984年联合成立了ISO/IEC小组,核心目的是开发一套统一的编码格式。1991年,推出了Unicode1.0,不过它并没有包含 CJK字符(即中日韩) ,可能是因为亚洲这几个国家的编码太复杂了。

ISO/IEC 8859

还记得上面我们提到ESCAII时讲过,欧洲国家在使用ESCAII时会出现,在128-255之间表示不同国家字符时会略有不同。ISO/IEC小组在1984年成立后的第三年(即1987年)开始启动ISO 8859标准的编写,ISO 8859是一系列单字节字符集的标准,采用了ESAII的部分编码,主要是为世界各地的不同语言(除中日韩)而单独编写的字符集,一共定义了15个字符集:从ISO 8859-1 到ISO 8859-16,需要注意的是没有ISO 8859-12, 据说-12号本来是预留给印度天城体梵文的,但后来却不了了之 。

比较常用的是ISO 8859-1,有些环境也称之为Latin-1,某些软件,比如mysql的默认编码格式就是Latin-1。

UCS

UCS( Universal Character Set  通用字符集)是一个超级大的字符集,它包含了已知的所有字符,并且它为每一个字符都分配一个唯一的代码。这其实保证了UCS与其他字符的双向兼容,即将任何编码格式的文本转换成UCS,然后再翻译回原编码,不会丢失任何信息。

UCS有两种编码方案:UCS-2和UCS-4,UCS-2使用两个字节编码(Unicode默认以UCS-2编码),UCS-4使用四个字节编码。UCS-2其实可以容纳的字符数为65536(2的16次方),而UCS-4可以容纳的字符数为2147483648(2的31次方)。其实对于UCS-2已经是完全够用了,基本可以包含世界所有国家的常用文字,如果需要考虑一些偏僻字,那么UCS-4则绝对可以满足了。

有的人可能有疑问,为啥有了Unicode还会有UCS,其实UCS是ISO/IEC推出的一种编码方式,而Unicode起初是美国的一些大公司联盟为了对抗UCS而推出的,后来两个组织发现,他们做的大部分事情都是重复的,干脆握手言和吧,于是后面就联手发布Unicode的后续版本,不过UCS也作为单独的版本发布过。

UTF

随着计算机网络的发展,Unicode如何在网络上传输也是必须考虑的问题,因为Unicode采用两个字节编码,如果用Unicode去表示一个ASCII,那么其第一个字节就始终为0(因为ASCII只需要一个字节)。这就造成了较大的空间浪费,于是UTF系列的编码应运而生,其最大特别是可变字节编码,这样可以节省带宽,提高网络传输效率。

UTF-8: 使用1~4个字节编码,其中ASCII用1个字节编码、 拉丁文、希腊文 等用2个字节编码、大部分国家的常用字用3个字节编码、其他极少使用的生僻字用4个字节编码。

UTF-16: 使用2个或4个字节编码,其中ASCII用2个字节编码、其他字符使用四个字节编码

UTF-32:  等同于UCS-4,对于所有字符都使用四个字节来编码

GB13000

前面提到1993年,ISO/IEC组织推出了Unicode1.0,不包含中日韩语言,但是紧接着ISO/IEC就推出了Unicode1.1版本,支持了中日韩语言。中国的标准组织考虑到自己也得有一个字符集,能够走向世界,于是将Unicode1.1中所有的内容全部搬过来,然后又经过部分修订完善,发布了GB130000。

GBK

GBK(K其实是拼音Kuo Zhan的首字母)是对汉字编码的扩展,这个微软指定的编码格式。随着计算机在中国的普及,微软意识到中国是一个巨大的市场,但是微软的系统在中国布局,肯定要面对编码兼容性问题,之前的GB2312基本满足了汉字的处理需求, 但对于人名、古汉语等方面出现的罕用字和繁体字,GB2312不能处理 。因此微软就利用GB2312中未被利用的编码空间,收录了GB130000中所有的字符,制定了GBK编码(还是两个字节),因此GBK是完全兼容G2312编码的。

GB18030

虽然GBK和GB130000编码已经包含了大部分的汉字和繁体字,但是并没有考虑到中国的少数民族的语言(中国有56个民族,12个民族有自己的语言)。在2000年,中国标准化组织又起草了GB18030标准,它参考UTF-8的编码方式,采用多编码方式(1或2或4个字节进行编码)。在2005年,发布GB18030-2005,共包含70244个汉字 。

ANSI

其实ANSI并不是一种特定的编码格式,是只存在于windows上的一种编码,猜测可能是微软为了能统一显示不同国家操作系统的编码而推出的。比如在在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码 ,在美国的windows操作系统中,就代表ASCII。windows主要通过 code page 来区分不同的编码格式,你可以在windows cmd窗口通过chcp命令切换code page。

总结

在平时的工作当中,如果碰到乱码,不要惊慌,只需要分析文件的编码格式、代码中对编码的处理方式等等(具体问题还得具体分析),在之后的文章中,牵扯到具体的问题,我们再具体分析。

发布了25 篇原创文章 · 获赞 1 · 访问量 5501

猜你喜欢

转载自blog.csdn.net/liwei_721/article/details/102979808
今日推荐