博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
谈谈字符编码
阅读量:4030 次
发布时间:2019-05-24

本文共 2172 字,大约阅读时间需要 7 分钟。

转摘地址: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://yqobi.baihongyu.com/

你可能感兴趣的文章
Preprocessing data-sklearn数据预处理
查看>>
Java实现Oracle到MySQL的表迁移
查看>>
子类A继承父类B, A a = new A(); 则父类B构造函数、父类B静态代码块、父类B非静态代码块、子类A构造函数、子类A静态代码块、子类A非静态代码块 执行的先后顺序是?
查看>>
android:style和theme
查看>>
wait()、notify()和notifyAll()、sleep()、Condition、await()、signal()
查看>>
Arrays.asList()
查看>>
Big Endian 和 Little Endian
查看>>
java中重写方法应遵循规则
查看>>
Comparable的使用(用于Arrays.sort)
查看>>
Comparator(用于Arrays.sort)
查看>>
对自己的计划
查看>>
反应c语言程序结构特点的程序
查看>>
Android错误总结
查看>>
android margin
查看>>
Drawable setBounds()中的rect
查看>>
markdown编辑器
查看>>
过拟合原因及解决
查看>>
支持向量机(SVM)初探
查看>>
决策树与随机森林初探
查看>>
相似度与距离算法种类总结
查看>>