什么是编码和解码
编码和解码概念
编码是信息从一种形式或格式转换为另一种形式的过程也称为计算机编程语言的代码简称编码。用预先规定的方法将文字、数字或其它对象编成数码,或将信息、数据转换成规定的电脉冲信号。编码在电子计算机、电视、遥控和通讯等方面广泛使用。解码,是编码的逆过程。—— 百度百科
我对编码和解码的理解:编码是根据一种编码规则,将我所要表达的信息用代码去表示出来;解码是根据解码规则(如果是对称加密的话,编码规则和解码规则是同一个规则),将代码解读出来。
举例说明
我们小时候经常会看一些谍战片,谍战片里总会出现一两个间谍,在敌方打探消息,然后用他和己方能看懂的方式去传递消息,如:摩斯密码。间谍敲出一串摩斯密码——三短三长三短,己方也会通过摩斯密码的规则来去解读对应的意思——SOS,己方就知道了这是求救信息,需要马上去营救被困在敌方的间谍。
在这个例子中,如果间谍明白此规则,发出三短三长三短,向外求救,但不知道此规则的敌方,只能听到这个声音,而不知道其中的含义,就“单纯”的以为间谍无聊发出此声音。
下图制定好的规则就指的是编码规则和解码规则,发出消息和解读消息的前提是双方都知道此规则,才会进行有效的消息传递。
对应到java程序中
为什么要编码?
最直接的回答就是防止我们的中文和一些特殊字符出现乱码的现象;详细点讲就是计算机只能识别0和1两个数字,所有的符号和文字都必须经过转换编码才能“翻译”成我们计算机认识的“语言”,相反也是,我们要想显示出我们能读懂的“语言”也必须要进行相应的解码才能从计算机中显示出我们能看懂的文字。
总的来说编码的原因有:
1.计算机中存储信息的最小单元是一个字节即 8 个 bit,所以能表示的字符范围是 0~255 个(2的8次方)
2.人类要表示的符号太多,每个符号无法用一个字节来完全表示
3.要解决这个矛盾必须需要一个新的数据结构 char,从 char 到 byte 必须编码
如何编码和解码呢?
那就是通过一种特定的编码格式转换,其实现在有很多中的编码格式,只要让计算机按照规定的编码格式进行转化,就可以显示成我们自己的字符。那现在就介绍一下目前最常见的一些编码格式:
首先我们要知道编码和编码格式是有区别的?
编码就是一个编号(数字)到字符的一种映射关系,是一种一对一的映射关系。
ASCII码
在计算机种中,1 字节对应 8 位二进制数,而每位二进制数有 0、1 两种状态,因此 1 字节可以组合出 256 种状态。如果这 256 中状态每一个都对应一个符号,就能通过 1 字节的数据表示 256 个字符。美国人于是就制定了一套编码(其实就是个字典),描述英语中的字符和这 8 位二进制数的对应关系,这被称为 ASCII 码。
ASCII 码一共定义了 128 个字符,例如大写的字母 A 是 65(这是十进制数,对应二进制是0100 0001)。这 128 个字符只使用了 8 位二进制数中的后面 7 位,最前面的一位统一规定为 0。
Unicode
Unicode 只是一个字符集,规定了符合对应的二进制代码,至于这个二进制代码如何存储则没有任何规定。它的想法很简单,就是为每个字符规定一个用来表示该字符的数字,仅此而已。
Unicode编码方案
之前提到,Unicode 没有规定字符对应的二进制码如何存储。以汉字“汉”为例,它的 Unicode 码点是 0x6c49,对应的二进制数是 110110001001001,二进制数有 15 位,这也就说明了它至少需要 2 个字节来表示。可以想象,在 Unicode 字典中往后的字符可能就需要 3 个字节或者 4 个字节,甚至更多字节来表示了。
这就导致了一些问题,计算机怎么知道你这个 2 个字节表示的是一个字符,而不是分别表示两个字符呢?这里我们可能会想到,那就取个最大的,假如 Unicode 中最大的字符用 4 字节就可以表示了,那么我们就将所有的字符都用 4 个字节来表示,不够的就往前面补 0。这样确实可以解决编码问题,但是却造成了空间的极大浪费,如果是一个英文文档,那文件大小就大出了 3 倍,这显然是无法接受的。
于是,为了较好的解决 Unicode 的编码问题, UTF-8 和 UTF-16 两种当前比较流行的编码方式诞生了。当然还有一个 UTF-32 的编码方式,也就是上述那种定长编码,字符统一使用 4 个字节,虽然看似方便,但是却不如另外两种编码方式使用广泛。
对于编码格式目前最常见的是UTF-8、GBK,它们都是用来序列化或存储 Unicode 编码的数据的,但是分别是2中不同的格式,他们都是 Unicode 的实现方式,当然也还有很多,这里就先介绍这两种啦。
- GBK
全称叫《汉字内码扩展规范》,是国家技术监督局为 windows95 所制定的新的汉字内码规范,它的出现是为了扩展 GB2312,加入更多的汉字,它的编码范围是 8140~FEFE(去掉 XX7F)总共有 23940 个码位,它能表示 21003 个汉字,它的编码是和 GB2312 兼容的,也就是说用 GB2312 编码的汉字可以用 GBK 来解码,并且不会有乱码。 - UTF-8
UTF-8 采用了一种变长技术,每个编码区域有不同的字码长度。不同类型的字符可以是由 1~6 个字节组成。
编码规则:
1.如果一个字节,最高位(第 8 位)为 0,表示这是一个 ASCII 字符(00 - 7F)。可见,所有 ASCII 编码已经是 UTF-8 了。
2.如果一个字节,以 11 开头,连续的 1 的个数暗示这个字符的字节数,例如:110xxxxx 代表它是双字节 UTF-8 字符的首字节。
3.如果一个字节,以 10 开始,表示它不是首字节,需要向前查找才能得到当前字符的首字节