字符

  1. **字符**是电子计算机或无线电通信中字母、数字、符号的统称,是数据结构中最小的数据存取单位。
  2. 通俗地讲,字符是人类信息载体的最小单元(文字、字母、运算符号、标点符号等)在计算机中的抽象。
  3. 在计算机中文本信息的呈现都是通过字符序列来实现的。如我们打开计算机上的一个文档或者使用浏览器查看文章。但是计算机不能识别“好”、“a”、“b”、“1”、“2”这样的字符,因此需要将字符转换为01才能进行存储和传输。

字符集

  1. 想让计算机处理字符,首先要告诉计算机字符和二进制数字之间的映射关系。这个映射表就是**字符集**。字符集中每个字符对应的唯一的二进制数叫“码点”(code point)。
  2. 最早计算机只被设计处理英文字母、数字和一些英文标点符号,这就是ASCII字符集。每个字符唯一对应一个8位的二进制数。28次方共256个字符,其中0~127用来表示常见字符。后128个是扩展ASCII码。
  3. 后来计算机被更广泛使用时候,ASCII编码不能满足计算机使用者对于字符处理的需求了。中国提出了GB2312GBK字符集。后来提出unicode字符集,用来表示世界上所有的字符。
  4. GB2312整个字符集分成94个区,每区有94个位。GBKGB2312的超集,其中收录了更多的字符。
  5. Unicode不是一次性定义的,而是分区定义。每个区可以存放65536个(216)字符,称为一个平面(plane)。目前,一共有17个(25)平面,也就是说,整个Unicode字符集的大小现在是221
  6. 1个基本平面,范围是U+0000 ~ U+FFFF
  7. 16个辅助平面,范围是U+010000 ~ U+10FFFF
  8. 所有最常见的字符都放在基本平面,这是Unicode最先定义和公布的一个平面。

剩下的字符都放在辅助平面。

编码

  1. 计算机在处理(存储、传输)字符的时候,需要根据字符集确认码点,然后把码点进行**编码**然后处理。为什么需要编码呢?
  2. 由于unicode字符集字符很多,因此码点数量巨大,如果直接用码点的二进制数表示这个字符,那么可能会存在很大的浪费。比如ASCII字符集中的字符在unicode字符集中都需要21位数字来表示。但是实际有效的长度只有8位,其他的都是0。因此在计算机实际处理字符时候,不会直接用码点表示字符,而是用另一个二进制数来表示字符,这个二进制数是变长的,在字符集前面的字符长度较小,字符集后面的较长。从码点到实际的字符表示,这之间的过程成为编码。反向叫解码。
  3. 从编码的长度是否固定,编码方法可以分为定长编码和不定长编码。定长编码的字符读取时候直接安装固定长度读取一个字符即可,不定长的编码还需要注意歧义性。例如我们对abcd分别编码为011110,那么110代码ca还是bd呢?为了避免歧义,在编码过程中会有一些手段,例如utf-8在编码中将字符对应的位数信息放到了编码后的二进制数中(utf-8的编码处理在后面详细说明),著名的哈夫曼编码将字符集组织成一个树,只有叶子节点才代表一个字符,通过这种方式保证读取字符时候能够判断是一个字符还是其他字符的前缀。
  4. 针对unicode字符集有不同的编码:utf-32utf-16utf-8UTF是<font style="color:rgb(0, 0, 0);">Unicode Transformation Format的缩写。</font>
  5. utf-32是定长编码,直接用码点表示字符。实际没有使用这种编码的。
  6. utf-16是变长的编码,有两种长度,2个字节和4个字节。
  7. utf-8是变长编码,有多种长度,可能是1~4个字节。

你可能会问为什么没有utf-24,24位即使定长,又比32位短,那是因为现代计算机一般习惯处理32位,并不能很好地处理24位数据。

为什么没有utf-24

UTF-8 最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

UTF-8编码规则

  1. 单字节的字符,字节的第一位设为0,对于英语文本,UTF-8码只占用一个字节,和ASCII码完全相同;
  2. n个字节的字符(n>1),第一个字节的前n位设为1,第n+1位设为0,后面字节的前两位都设为10,这n个字节的其余空位填充该字符unicode码,高位用0补足。

因此utf-8编码后就是下面的几种情况:

0xxxxxxx

110xxxxx 10xxxxxx

1110xxxx 10xxxxxx 10xxxxxx

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

跟据上表,解读 UTF-8 编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

  1. 在文本写和读的时候,需要使用同样的字符集和编码,否则就会出现乱码情况。