OC网络学习26:字符编码ASCII、Unicode、UTF-8探索

张建 lol

编码历史

最早只有 128 个字符被编码到计算机里,也就是 大小写英文字母、数字和一些符号,这个编码表被称为 ASCII 编码。例如:大写字母A的编码是65,小写字母z的编码是122。

但是要处理中文显然1个字节是不够的,至少需要2个字节,而且还不能和ASCII编码冲突,所以,中国制定了 GB2312 编码,用来把 中文 编进去,随着发展,又发现了一些局限,所以就有了 GBK,再继续往后增加了一些字符(如少数名族字体),GBK扩成了 GB18030。。你可以想得到的是,全世界有上百种语言,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。

因此,Unicode 应运而生。Unicode 把所有语言都统一到 一套编码 里,这样就不会再有乱码问题了。

Unicode标准也在不断发展,但最常用的是用2个字节表示1个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。

新的问题又出现了:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,在存储和传输上就得不偿失。

所以,本着节约的精神,又出现了把Unicode编码转化为 可变长度编码的UTF-8编码UTF-8编码 把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的 英文字母 被编码成 1个字节汉字 通常是 3个字节,只有 很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。

UTF-8编码 有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分。所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。

Charset

Charset(Character set)字符集:是对字符抽象表示的集合。包括世界上各种文字、符号和字符

字符集 只是一个规则集合的名字,对应到真实生活中,字符集就是对某种语言的称呼。例如:汉语、英语、日语

字符编码

对于一个字符集来说,要正确编码一个字符需要三个元素:

  1. 字库表(character repertoire)

字库表:是一个相当于所有可读或者可显示字符的数据库。字库表决定了整个字符集能展现表示的所有字符范文

  1. 编码字符集(coded character set)

编码字符集:即用一个编码值code point来表示一个字符在字库中的位置

  1. 字符编码(character encoing)

字符编码:将编码字符集和实际存储数值之间的转换关系

ASCII

ASCII:American Standard Code for Information Interchange,美国信息互换标准代码。

1
2
3
英文:1个英文字母(不分大小写)占1个字节空间

中文:1个中文汉字占2个字节空间

ASCII 只有 128 个字符,表示英文字母的大小写、数字和一些符号,但由于其他语言用 ASCII 编码表示字节不够。例如:常用中文需要 2 个字节,且不能和ASCII冲突,中国制定了 GB2312 编码格式,相同的,其他国家的语言也有属于自己的编码格式。

Unicode

Unicode统一码,它将世界各种语言里的每一个字符都定义了一个 唯一的编码。这意味着世界上所有的语言都可以使用它,而不会出现冲突。

1
2
3
英文:1个英文字母占2个字节空间
中文:1个中文汉字(含繁体)占2个字节空间
符号:英文标点占1个字节,中文标点占2个字节。例如:英文句号 `.` 占1个字节,中文句号 。占2个字节
  1. 虽然Unicode编码了所有字符,但是在很多情况却不能直接使用它,为什么?

因为在Unicode中有些字符占一个字节,如:英文字符,有些字符则占两个字节,如:常用汉字。但是当我解码一串中英字符混合的Unicode编码时,我是一次解码一个字节呢还是两个字节呢?UTF-8,UTF-16,UTF-32解决了这个问题。

  1. 转义字符,反斜杠 \
  • \U 后跟 8位16进制数

  • \u 后跟 4位16进制数

UTF

  1. UTF-8

UTF-8:(8-bit Unicode Transformation Format,Unicode转换格式),它是一种Unicode编码的实现,即 可变长度字符编码

1
2
英文:1个英文字母占1个字节空间
中文:1个中文汉字(含繁体)占3个字节空间

为了解决上述问题,又出现了 把Unicode编码转化为可变长度编码UTF-8编码UTF-8编码将Unicode字符按数字大小编码为1-6个字节,英文字母被编码成1个字节,常用汉字被编码成3个字节,如果你编译的文本是纯英文的,那么用UTF-8就会非常节省空间,并且ASCII码也是UTF-8的一部分。

  1. 进一步理解

UTF-8编码变长编码。最小编码单位(code unit)为一个字节。一个字节的前1-3个bit为描述性部分,后面为实际序号部分。

  • 0xxxxxxx:如果是这样的格式,表示在 UTF-8 中这个 字符 用这 一个字节 即可表示,读取这一个字节即可解码成一个字符。因为第一位已经规定为 0,所以只有 7 位能用来放置Unicode编码。

  • 110xxxxx 10xxxxxx:如果是这样的格式,则表示在 UTF-8 种这个 字符两个字节 可以表示,读取两个字节可以解码成一个字符。110 表示此字节为开头字节,10 表示此字节不是开头字节。因为第有5位已经固定,所以仅有11位可以用于存放Unicode编码。

  • 1110xxxx 10xxxxxx 10xxxxxx:如果一个字节以 1110 开头,那么代表当前 字符三字节字符,占用3个字节的空间。110 之后的所有部分(5个bit)加上后两个字节的除 10 外的部分(12个bit)代表在Unicode中的序号。且第二、第三个字节以10开头。

来看一个UTF-8的例子:

发现其中规律:

  • 1个字节的UTF-8十六进制编码是以比8小的数字开头的

  • 2个字节的UTF-8十六进制编码是以C或D开头的

  • 3个字节的UTF-8十六进制编码是以E开头的

UTF-8、UTF-16和UTF-32区别

  • utf-32 是采用每个字符 使用 4个字节 进行存储。

  • utf-16 是采用每个字符 使用 2或4个字节 进行存储。

    • U+0000 ~ U+FFFF:使用两个字节表示。

    • U+10000 ~ U+10FFFF:使用四个字节表示

  • utf-8 比较特殊,它是 变化的,根据字符的长度来动态变化,来表示实现编码。

    • utf-8 遇到纯英文,就用1个字节,8bit位变化来实现,
    • utf-8 遇到中文,用2个字节,16bit位变化来实现。
    • utf-8 遇到韩文,用3个字节,24bit位变化来实现。

Unicode 和 UTF-8

Unicode 就是上文中提到的 编码字符集,而 UTF-8就是字符编码,即Unicode规则字库的一种实现形式。

三种编码之间的联系

在计算机系统通用的字符编码工作方式:

  1. 在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换成UTF-8编码
  2. 用记事本编辑的时候,从文件读取的UTF-8字符被转换成Unicode字符到内存中,编辑完成后,保存的时候把Unicode转换为UTF-8保存到文件,如下图:

  • Post title:OC网络学习26:字符编码ASCII、Unicode、UTF-8探索
  • Post author:张建
  • Create time:2023-08-09 08:39:53
  • Post link:https://redefine.ohevan.com/2023/08/09/OC网络/OC网络学习26:字符编码ASCII、Unicode、UTF-8探索/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.