4

字符集与编码 - itbsl

 2 years ago
source link: https://www.cnblogs.com/itbsl/p/16165971.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

字符集与编码

一个比特(bit)可以是0,或者是1,8个比特(bit),组成一个字节(byte)。全为0时代表数字0,全为1时代表数字255。

一个字节可以表示256个数字,两个字节可以表示65536个数字。

更多的字节,可以有更多的组合,就可以表示更大的数值范围。

整数可以这么存,那字符呢?一堆二进制的0和1,怎么也算不出字母A吧。不能直接表示,那就通过数字中转一下。只要给它指定一个数值编号,要存储字符时,就存储这个数值。要读取时,按照映射关系找到这个字符。

像这样收录许多字符然后给它们一一编号,得到一个字符编号对照表,这就是“字符集”。

ASCII字符集只收录了128个字符,其扩展字符集也只有256个。(ASCII最初被设计的目的也只是用来映射英文体系所需要的字符)

这在只使用英文的国家貌似没什么问题,但是随着世界的互联,其它非英语母语的国家该怎么办呢?比如汉字、日文等。

针对汉字,最先设计了GB2312字符集、但是GB2312不包含繁体字,所以又设计了BIG5字符集,但是依然有很多字符没有被收录,其它国家的字体也不在其中

与其不断推出收录更多字符的字符集,还不如本着全球化统一标准的目的,制作一个通用字符集,Unicode学术学会就是这样做的,这个字符集就是Unicode,它于1990年开始研发并于1994年正式公布,实现了跨语言跨平台的文本转换与处理,字符集促成了字符与二进制的合作。但是有了字符集就万事大吉了吗?那怎么存储(eggo世界)这个内容呢?

直接的想法是,找到每个字符对应的编号,存成二进制,如果使用unicode字符集,拿到他们的编号,直接组合会得到这样一大串二进制位

问题出现了,该怎么知道这一长串内容是要按照下面的方式划分的呢?

也可以按照下面的方式划分呀

所以,照搬编号的方式,行不通!!!

那现在我们可以知道了,编码完成之后还需要解决的一个问题是如何划分字符边界。

其中一个方法可以这样,不管编号多大多小,统一按照最长的编码的来,位数不够的高位补0嘛

这就是定长编码,这样就可以解决字符边界的问题,但是可以发现,这样就太浪费内存了,而且字符集收录的符号越多,编号跨度就越大,定长编码造成的浪费就越显著,还得再想办法,定长编码不行,那就“变长编码”,小编号少占字节,大编号多占字节。

但是怎么划分字符边界呢?来看一种解决方案,如果编号属于[0,127],就占用一个字节,且最高位固定标识为0。如果属于[128,2047],就占用两个字节,且有固定标识位110和10,三个以及更多字节的编码也遵循这样的规则

以二进制数字01100101,这个字节最高位是零,就表示这个字符只占一个字节,除去标识位,剩下的7位就是该字符的二进制编号,转换成十进制就是101,对应字符e,“世”字同理。

这样划分字符就不成问题了。刚刚我们做的是解码,现在来编码试试,世界的“界”字在Unicode字符集中编号为30028,符合区间[2048,65535],所以要占用三字节,使用下面这个模板。

然后将编号30028转换成二进制01110101 01001100,再对应填到模板中

好的,这样就编码完成了, 我们刚刚用的其实就是UTF-8编码,也就是Go语言默认的编码方式。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK