上周同事组内分享了编码相关的内容。之前自己也总结过,但过了一段时间后发现记忆有点模糊。希望能从一个角度讲好编码这件事,理解型记忆。
编码的理解
在计算机的世界中,只有0和1。0和1组成的2进制能唯一对应一个数字。因此我们所见的所有文字,所有符号,要想在计算机中表现,只能先对应到一个数字上。比如0表示a,1表示b。你以为人类的文字很多,其实不然,汉字也就几万的规模而已。将所有人类日常用到的符号,全部给一个数字编号,然后将数字转换成计算机的01,编码的过程也就完成了。
任何一个编码系统都是如此,也只能如此。这个过程中唯一能产生的区别就是符合对应的数字可能不同。比如我0表示A, 你的0表示a。另外也可能我只表示英文字符,别的字符不包含,比如ascii码,而有些包含汉字,不包含拉丁文。这些都是细枝末节的区别。
来对汉字进行编码
如果要对汉字进行编码,首先是获取到想要编码的所有汉字,比如6万个。从0到6万给个编号,这6万个汉字就已经编码好了。
剩下的问题不过是如何在计算机中进行保存。毕竟编号最小的只需要占用1bit的空间,而编号最大的可能需要16bit空间(2^16=65536)。
不同编码的区别
除了最开始说的最细枝末节的区别,不同编码之间最大的区别在于,如果在计算机中表示相应的数值。
比如上面提到的,要表示从0到6万之间的所有数,如何在计算机中表示。最简单的是,每个数分配16bit的空间也就是2个字节来表示。没有一点问题。
但对于1个字节就能表示的数,另外一个字节就全是0,浪费掉了。特别是要表示英文文献时,大部分都是ascii码,一个字节就能搞定的事情,空间相当于浪费了一半。
上面用两个字节来表示成为固定长度表示。与之相对的就是变长表示法。对于一个字节能表示完的,我就用一个字节,万不得已的时候,我用更多的直接来表示。
unicode 编码
Unicode编码是一套规范,规定的是数字和符号之间的对应关系。
里面具体的编码规则如utf-16, utf-8是遵循这套规范的,且明确在计算机中保存这些数字的格式。
其中utf-16 是固定使用两个字节的长度来表示。因此与ascii码不兼容(当需要表示的字符只是ASCII码时,是否与ASCII 编码后的二进制一样)--使用utf-16表示abc之后,其二进制使用ASCII规范解码后为0a0b0c。
固定字节长度的编码都很好实现,解码工作也非常容易做。但问题有两个
- 空间浪费的问题。
- 解码时不安全的问题。如果因为某些原因,遗漏了一个字节,则后面所有的解码都将错误。
utf-8是使用最多4字节的变长编码。
- 与ASCII兼容。ASCII编码是一个字节,且首尾为0。因此当解码时,发现一个字节首位为0,当成一个字节解读。
- 在此基础上,如果首位为1, 则表明这次编码一定不是一个字节。可能是2,3,4个字节三种情况。