谈谈字符编码

转摘地址:http://blog.segmentfault.com/stephenlee/1190000000489202

这几天用到一家公司的短信 API,结果就遇到件囧事,因为编码格式不对,发过去的文字解析出了错误。于是就想到除了刚开始学习 web 的时候遇到过编码问题,似乎很久没有因为这个问题困扰过了,所以也就从没有仔细研究过,今天时间比较充裕,所以研究了下编码问题,特写博文一篇记录下心得体会。

起源 - ASCII

我们都知道在计算机内部,所有的数据在存储和运算的时候都应该使用二进制进行表示。例如字母,数字等等。通过二进制进行表示,我们可以指定很多规则来表示这些字符,为了避免不一致性,美国国家标准学会(American National Standard Institute , ANSI )制定了 ASCIIAmerican Standard Code for Information Interchange,美国信息交换标准代码)编码。
ASCII 码使用 7 位二进制数来表示 128 个字符,也就是用一个字节来表示,最前的一位默认为 0

请输入图片描述

我们都知道计算机是美国人发明的,接着美国人又制定了一套规则 ASCII 码用来在计算机中表示自己的语言和符号,由于英语的特殊性(26个字母搞定一切),所以一个字节的二进制就可以解决问题。
后来又有些符号和一些外来字母也需要表示,怎么办呢?我们前面讲到 ASCII 码刚开始制定时虽然用了一个字节的长度,但是空着最前的一位,所以只用了7位,还有一位没用起来,那么如果把这一位也用起来的话,也就是8位二进制,那么就可以表示256个字符了,于是扩展 ASCII 码诞生,保留原始的7位的基础上,使用了最前的一位。

请输入图片描述

发展 - GB2312

随着计算机的发展,越来越多的国家也使用上了计算机,那么也就需要计算机来展示自己国家的字符了,以中国为例,汉字的数量之多是英文字母无法想象的,区区一个字节是根本不可能装下庞大的汉字体系。所以我们中国自己制定了一套编码体系,称为 GB2312(信息交换用汉字编码字符集),使用两个字节,也就是16位二进制,那么算下来最多就可以存下 65536 个字符了。最后收录了 6763 个汉字,覆盖了常用词的百分之90,所以基本是满足了计算机处理汉字的需求。为了兼容 ASCII,大部分使用 GB2312 的程序都采用 EUC 存储方法。
这里虽然只介绍了 GB2312,但是也隐含着一个问题,世界上这么多国家,每个国家都有不同的文化和语言,如果都制定属于自己的字符编码,那么就乱套了。
对计算机而言,当你通过设备输入字符时,它会根据你预置的编码规则来识别,如果两台电脑内的编码规则不一致,那么就无法识别彼此的符号信息了,对于以信息交流为目的的计算机体系而言,这无疑是个严重的问题。

统一 - Unicode

Unicode 又称为统一码或万国码,根据它的译名就能知道它的作用。它的出现就是为了解决字符编码的不一致性,虽然这期间也出现了不少很广泛使用的字符编码,但直到 Unicode 的出现才可以说真正出现了一套能容纳全球语言符号的编码规则。这里我们要注意,Unicode 仍然是支持 ASCII的。
Unicode 虽然能容纳上百万数量的字符,但是它只是一个巨大的字符集,仅仅规定了每个符号的二进制代码,却没有制定细化的存储规则,例如当用三个字节存储一个字符时,它同时也可以被理解为存储了三个 ASCII 码,另外我们之前知道 ASCII 码只需要一个字节,但是如果 Unicode 规定每个字符使用三个字节来存储的话,那岂不是额外浪费两个字节的空间?所有这些未细化的问题都将导致 Unicode 的不一致性。
在 Unicode 出现之前,所有的字符集都是和具体编码方案绑定在一起的,都是直接将字符和最终字节流绑定死了,例如 ASCII 编码系统规定使用7位来编码 ASCII 字符集;GB2312 使用最多2个字节来编码所有字符,并且规定了字节序。这样的编码系统通常用简单的查表,也就是通过代码页就可以直接将字符映射为存储设备上的字节流了。

请输入图片描述

但这种方式的缺点在于,字符和字节流之间耦合得太紧密了,从而限定了字符集的扩展能力。因此 Unicode 在设计上考虑到了这一点,将字符集和字符编码方案分离开。每个字符在 Unicode 字符集中都能找到唯一确定的编号,但是决定最终字节流的却是具体的字符编码。

请输入图片描述

细化 - UTF-8

首先我们要明确 UTF-8(8-bit Unicode Transformation Format)是在统一码(Unicode)基础上细化并优化后的一种长度可变的字符编码方式,它是实现 Unicode 的方式之一,正如 @jysperm 所说,除了 UTF-8,还有UTF-16,UTF-32 等都可以实现 Unicode,但是 UTF-8 相对而言是用的最为广泛的。UTF-8 可以使用1到4个字节来,它通过自身的规则能够灵活地变化长度来存储 Unicode 字符。

请输入图片描述

总结

我们可以用记事本来测试不同字符编码的差异:

请输入图片描述

现在,我终于明白了部分关于编码的知识,不过博文中间可能有些概念理解得不是特别正确,如有错误,欢迎指正。

参考

http://www.joelonsoftware.com/articles/Unicode.html
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
《关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值