> For the complete documentation index, see [llms.txt](https://chanshiyu.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://chanshiyu.gitbook.io/blog/shi-yu/2019/07-no.md).

# 07 字符编码の小常识

一直以来都对各种字符编码傻傻分不清楚，被工作中经常出现的 ASCII、Unicode、UTF-8 等各类不同的编码术语折腾得偏头痛，所以查了点资料文档了解下各种编码方式的原理。

### 编码

众所周知，在计算机内部，所有信息最终都表示为一个二进制值，每个二进制位有 `0` 和 `1` 两种状态。八个二进制位（bit）组成一个字节（byte），一共可以表示 2^8 = 256 种状态。一个状态对应一种符号，即共有 256 种符号，从 `00000000` 到 `11111111`。

#### ASCII 码

ASCII 码是美国制定了一套字符编码，对英语字符与二进制位之间的关系，做了统一规定。ASCII 码使用一个字节来表示一个字符，一共规定了 128 个字符的编码，这些字符只用一个字节的后 7 位，第一位统一为 `0`。

对于英语 ASCII 编码的 128 个符号足够使用，但对于其他语言来说却不够，所以一些语言将字节中闲置的第一位编入新的符号，充分使用 256 个字符。但这样造成了同一个编码在不同语言编码体系中表示不同，造成混乱。

第二个问题是对于一些亚洲国家的文字，比如中文，256 个符号远远不够，必须使用多个字节表示一个符号。比如简体中文的 GB2312 编码方式，使用两个字节表示一个字符，最多可以表示 256 x 256 = 65536 个符号。

#### Unicode

由于世界上存在着多种编码方式，同一个二进制数字可以被解释成不同的符号。因此，要想打开一个文本文件，就必须知道它的编码方式，否则用错误的编码方式解读，就会出现乱码。由此 Unicode 应运而生。

Unicode 是一个统一编码集合，类似于世界语，它将世界上所有符号都赋予了一个第一无二的编码。由于每个字符的编码都是唯一的，这样避免了字符编码混乱的问题。

需要注意的是 Unicode 只是一个符号集，它只规定了符号的二进制代码，却没有规定这个二进制代码应该如何存储。

#### UTF-8

UTF-8（8-bit Unicode Transformation Format）是 Unicode 的实现方式之一，同时也是互联网上使用最广的一种 Unicode 的实现方式。它规定了 Unicode 符号的存储方式。UTF-8 最大的一个特点，就是它是一种变长的编码方式。它可以使用 1\~4 个字节表示一个符号，根据不同的符号而变化字节长度。

UTF-8 的编码规则有两条：

1. 对于单字节的符号，字节的第一位设为 `0`，后面 7 位为这个符号的 Unicode 码。因此对于英语字母，UTF-8 编码和 ASCII 码是相同的。
2. 对于 `n` 字节的符号（`n > 1`），第一个字节的前 `n` 位都设为 `1`，第 `n + 1` 位设为 `0`，后面字节的前两位一律设为 `10`。剩下的没有提及的二进制位，全部为这个符号的 Unicode 码。

UTF-8 的解读方式：如果一个字节的第一位是 `0`，则这个字节单独就是一个字符；如果第一位是 `1`，则连续有多少个 `1`，就表示当前字符占用多少个字节。
