一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
什么叫字符
组成数据和信息的文字、字母、数字以及各种符号的统称。-- 这是网上抄来的
比如说:
- 一个汉字就是一个字符
- 一个英文字母也是一个字符
- 一个数字也是一个字符
- 一个标点符号也是一个字符
- 任意语言任意符号都是一个字符
什么叫字符集
字符集就是一个集合,这个集合把字符按照编号进行收编。
那么是不是一个字符集就能包含所有的字符呢?
显然是不对的。
比如说 ASCII 字符,只包含了英文字母和数字,和一些常用的电脑符号,比如说回车,空格等。
现在最大的字符集是什么:Unicode 字符集,几乎包含了所有出现的字符,甚至emoji表情也被认为是字符,被包含了进去。
字符编码
字符集只是一个集合,告知了每一个字符的编号,但是,他并没有告知,如何在计算机中来存储这个编号。
例如,在Unicode字符集中,汉字码的编号是U+7801。
此时,如果你要存储这个码字,你完全可以存一个整数(int):7801。
那么,只要读取这个 int 的程序或者系统,他也跟你一样,明白 7801这个整数就是码字的话,那么就是可以的。
不过,我们只是将码这个字进行了编码,这是不够的,我们要考虑这个字符集中,所有的字符该怎么存的问题。
至少:
- 不能重复,也就是不能说两个字符,都存
7801 - 尽量占少一点字节,你不能一个字符,存个几十个字节,那么一篇小说,就炸了
ASCII 是如何编码的
当我们说ASCII的时候,既是再说这个字符集,也是在说这个编码,因为早期,这两个概念并没有分得太开。
这个编码很简单,因为他就包含127个字符(不算扩展), 用一个字节来存储就行了,每一个数字代表一个字符。
例如:
- A --> 0x41
- B --> 0x42
等等
对Unicode字符集进行编码
这是一个巨大的工程,其实。
首先,为了兼容ASCII, 必须保证,原先用ASCII编码存储的内容,这个新的编码照样能读出来。
比如说:
"ABCDEFG" 这一段文字,如果用ASCII编码保存:
0x41 0x42 0x43 0x44 0x45 0x46 0x47
就是7个字节,每个字节的内容如上。
现在,用新的编码,来读取上述七个字节,要依然能解析出:
"ABCDEFG" 这一段文字。
也就是说,对于ASCII码部分,新编码要完全一致。
但是,ASCII码只用了一个字节,不可能包含所有的字符。
于是,一种解决方案就提出来:
变长码
就是说,对于字符集里的字符来说,编码储存之后的字节数,并不一定要相等。
有的用一个字节,有的用两个字节,等等。
UTF-8 这种编码方式
此时此刻,我们来讲一讲现在应用最多的Unicode编码方式:UTF-8。
- 首先,他是一个变长码。
- 第二,兼容ASCII。
举个例子:
英文A --> Unicode编号:U+0041 --> UTF-8编码: 0x41 占一个字节,并且与ASCII一致。
汉字码 --> Unicode编号:U+7801 --> UTF-8编码: 0xE7 0xA0 0x81 占三个字节。
从这里可以更加清晰的看出编号和编码的概念。
UTF-8 的编码过程
所谓编码过程,就是你知道一个字符的编号之后,该如何把这个编号,转化成具体的字节的过程。
我们用 码这个汉字来说明这个过程:
- 首先找到
码的编号是U+7801 - 然后来看一下这个图(来自维基百科)
这个图的含义是,如果编号在
U+0000 --> u+007F 之间,那么用第一行的逻辑。
U+0080 --> u+07FF 之间,那么用第二行的逻辑。
U+0800 --> u+FFFF 之间,那么用第三行的逻辑。
U+10000 --> u+10FFFF 之间,那么用第四行的逻辑。
很明显,我们的U+7801属于第三行。
那么第三行的逻辑是什么?
首先,第三行,就已经固定了三个字节了,并且三个字节的高位,已经写死了
第1个字节:1110xxxx
第2个字节:10xxxxxx
第3个字节:10xxxxxx
剩下就是,如何将7801填充进上面的xxxxxxxxxx里面去。
也简单:
我们来看一下x的个数,正好是16个,也就是两个字节。
我们将 7801 看做 0x78 0x01 ,也正好是两个字节
直接将这个两个字节的内容,按顺序放入上面的xxxx里面去:
第1个字节:1110xxxx -> 1110 0111 -> 0xE7
第2个字节:10xxxxxx -> 10 1000 00 -> 0xA0
第3个字节:10xxxxxx -> 10 00 0001 -> 0x81
于是,码->0xE7 0xA0 0x81
so easy ~~~