跳到正文
BCBinary Code Translator
菜单
返回博客
指南

文字为什么能变成二进制?从 ASCII 到 Unicode 和 UTF-8

用 A、中、😀 三个例子说明字符、Unicode 码点、UTF-8 字节与二进制之间的关系,并解释为什么一个字符不一定等于一个字节。

3 分钟阅读
作者 Binary Code Translator
#binary#text#encoding#computer-science

文字不是直接“变成 0 和 1”

我们在聊天软件里输入一句话时,程序处理的是字符;真正写入文件、内存或网络的数据,则需要按照某种编码规则表示成字节。字节再由 bit 组成,因此最后可以写成一串 0 和 1。

这里最容易混淆的是:字符、Unicode 码点、编码后的字节和二进制位,不是同一个概念。

数字电路通常用两个可区分的逻辑状态来表示一个 bit,并把这两个状态记作 0 和 1。在本文讨论的现代 Web 和 UTF-8 语境中,1 个 byte(字节)就是 8 个 bit。但这并不意味着“一个字符一定占 8 个 bit”——字符要占多少字节,取决于使用的字符编码。

先分清四层:字符、码点、字节、bit

可以把文本保存过程理解成下面这条链路:

  1. 字符:人看到的文字或符号,例如 A、中、😀。
  2. Unicode 码点:Unicode 给字符分配的编号,例如 A 是 U+0041。
  3. 编码后的字节:UTF-8 等编码方案把码点转换成一个或多个字节。
  4. bit:每个字节都可以继续写成 8 位二进制。

因此,“文字转二进制”并不是把字形直接翻译成 0 和 1,而是先确定字符的编号和编码方式,再得到具体字节。

ASCII:为什么 A 可以写成 01000001

ASCII 是早期英文文本中最常见的字符编码标准之一。标准 ASCII 使用 7 bit,可表示 128 个编号(0 到 127),包括英文字母、数字、标点和控制字符。

例如:

字符 ASCII 十进制 十六进制字节 二进制
A 65 41 01000001
B 66 42 01000010
a 97 61 01100001
0 48 30 00110000

A 的 ASCII 编号是 65,也就是十六进制 0x41。如果把这个值放在一个 8 bit 的字节里,就是:

01000001

这也是为什么在 UTF-8 中,A 仍然只占 1 个字节:UTF-8 对 ASCII 的 0–127 范围保持兼容。

Unicode 和 UTF-8 分别解决什么问题

ASCII 的范围太小,无法表示汉字、绝大多数其他文字以及 emoji。Unicode 解决的是“每个字符应该对应哪个编号”的问题,这个编号叫码点(code point)。

例如:

  • A → U+0041
  • 中 → U+4E2D
  • 😀 → U+1F600

但 Unicode 码点本身并不等于文件里的字节。还需要 UTF-8、UTF-16 等编码方案,把码点转换成实际字节序列。

UTF-8 是目前 Web 和跨平台文本交换中最常见的 Unicode 编码之一。它使用可变长度表示:一个 Unicode 码点会占 1 到 4 个字节。

A、中、😀 在 UTF-8 中到底是什么

下面三个例子都可以直接用程序验证:

字符 Unicode 码点 UTF-8 字节(十六进制) UTF-8 字节(二进制) 字节数
A U+0041 41 01000001 1
中 U+4E2D E4 B8 AD 11100100 10111000 10101101 3
😀 U+1F600 F0 9F 98 80 11110000 10011111 10011000 10000000 4

所以:

  • A 在 UTF-8 中是 1 个字节,也就是 8 bit。
  • 中 在 UTF-8 中是 3 个字节,也就是 24 bit。
  • 单个码点 😀 在 UTF-8 中是 4 个字节,也就是 32 bit。

这就是“汉字为什么不是 8 个 bit”的直接答案:UTF-8 并没有规定一个字符只能使用一个字节。 8 bit 只有 256 种组合,显然不足以直接覆盖 Unicode 中的大量文字和符号。

还要注意一个更严格的细节:用户眼中的“一个字符”也不一定只对应一个 Unicode 码点。例如某些带组合符号的文字和 emoji 序列会由多个码点组成,因此它们在 UTF-8 中可能超过 4 个字节。本文中的 😀 是单一码点示例。

一个字符不等于一个字节

“character = byte”只在很有限的场景下成立。以 UTF-8 为例:

  • 基础 ASCII 字符通常占 1 字节;
  • 很多欧洲文字会占 2 字节;
  • 常见汉字通常占 3 字节;
  • U+10000 以上的码点(例如 😀)占 4 字节。

因此,按“字符数”截断 UTF-8 数据时,不能简单按字节数切。反过来,看到一串二进制也不能只按每 8 bit 直接猜字符,还必须知道这些字节采用了什么编码。

从输入到保存,实际发生了什么

以输入一个汉字为例,过程通常比“按键 → ASCII”复杂得多,尤其是中文输入法参与时。更合理的简化流程是:

  1. 键盘和输入法把用户操作转换成程序能够处理的字符。
  2. 应用程序内部用某种 Unicode 表示来处理这些字符。
  3. 保存文件或发送网络数据时,程序选择具体编码,例如 UTF-8。
  4. 编码器把 Unicode 码点转换成字节。
  5. 存储设备和网络传输处理的是这些字节;需要展示文本时,再按同一种编码解码回来。

如果编码和解码使用了不同规则,就可能出现问号、替换字符或错误文字。这是编码不匹配,并不等于数据被“加密”了。

编码、压缩、加密是三件不同的事

这三个概念经常被混在一起:

概念 目的 例子
编码(encoding) 按约定把字符或数据表示成另一种形式 Unicode 码点通过 UTF-8 变成字节
压缩(compression) 减少数据体积,之后可以解压恢复 ZIP、gzip、RLE
加密(encryption) 在没有密钥时隐藏原始内容 AES、ChaCha20

例如连续的 AAAAAA 可以用类似 RLE(游程编码)的思路记录成“6 个 A”这样的“次数 + 值”结构,但这属于压缩,不是 ASCII 或 UTF-8 本身的规则。未压缩时,这 6 个 A 在 UTF-8 中仍然是 6 个 41 字节。

同样,加密后的结果叫密文(ciphertext)。密文可能看起来无法直接阅读,但不应该把它简单称为“乱码”。编码只是表示方式,二进制表示本身也不提供保密性。

如何把文本转换成二进制

如果已经确定使用 UTF-8,转换步骤就很清楚:

  1. 取得字符对应的 Unicode 码点。
  2. 用 UTF-8 把码点编码成字节。
  3. 把每个字节写成 8 位二进制。

例如 中:

  • Unicode 码点:U+4E2D
  • UTF-8 字节:E4 B8 AD
  • 二进制:11100100 10111000 10101101

这里真正决定二进制结果的是 UTF-8 字节序列。换一种编码,同一个字符得到的字节可能不同。

自己验证

你可以直接用站内工具检查结果:

实际调试文本问题时,建议同时查看十六进制字节。相比一长串 0 和 1,E4 B8 AD 这样的写法更容易核对 UTF-8 边界。

记住这条关系就够了

理解文本与二进制,不需要把“计算机只懂 0 和 1”当作全部答案。更准确的关系是:

字符 → Unicode 码点 → UTF-8 等编码产生的字节 → 每个字节由 bit 表示。

只要把这四层分开,就能解释为什么 A 是 1 个 UTF-8 字节、中 是 3 个字节、😀 是 4 个字节,也能避免把编码、压缩和加密混为一谈。

Cookie 偏好设置

管理你的 Cookie 偏好。必要 Cookie 无法关闭。

必要 Cookie

必要

用于语言选择、隐私选择和网站基础功能,属于必需项。

Cookie: NEXT_LOCALE

分析 Cookie

可选的分析 Cookie 可帮助我们了解访问情况并改进网站。

Cookie: _ga, _gid, _gat, _clck, _clsk

广告 Cookie

可选的广告 Cookie 可能用于展示相关广告并衡量广告效果。

Cookie: __gads, _gcl_au, IDE