你输入的每个字符——从 A 到 中 再到 😂——在计算机中都以一串 0 和 1 存储。连接人类可读文本与机器二进制的桥梁是字符编码。本文解释文本如何转换为二进制,涵盖基础 ASCII 标准、向 Unicode 的过渡以及驱动现代网络的实用编码方案(UTF-8、UTF-16)。你将获得清晰的思维模型、一个完整的示例以及诊断编码相关问题的知识。

什么是字符编码?
字符编码是一组字符(字母、数字、符号)与其数值表示之间的映射。计算机存储数字;编码告诉它哪个数字对应哪个字形。如果没有一致的编码,相同的二进制序列在不同系统上可能被解释为不同的字符——这就是乱码的根本原因。
ASCII:基础
ASCII(美国信息交换标准代码)于 1963 年引入,使用 7 位表示 128 个字符:控制码(0–31)、可打印字符(32–126)和删除字符(127)。实际存储占用 1 字节(8 位),高位通常设为 0。
需要记住的关键 ASCII 值:
| 字符 | 十进制 | 二进制 |
|---|---|---|
| 空格 | 32 | 0010 0000 |
0 |
48 | 0011 0000 |
A |
65 | 0100 0001 |
a |
97 | 0110 0001 |
注意大写和小写字母相差正好 32('a' - 'A' = 32)。这种规律性使得大小写转换在代码中非常容易。
超越 ASCII:Unicode 与编码方案
ASCII 只覆盖英语。要表示其他语言的字符(如中文、阿拉伯语、表情符号),我们需要更大的字符集。Unicode 为每个字符分配唯一的码位(例如 中 的 U+4E2D),但没有规定如何将这些码位存储为字节。这就需要编码方案如 UTF-8 和 UTF-16。
UTF-8:变长、兼容 ASCII
UTF-8 是网络上主流的编码。每个字符使用 1 到 4 字节:
- ASCII 字符(U+0000–U+007F):1 字节(与 ASCII 相同)
- 拉丁、希腊等(U+0080–U+07FF):2 字节
- 中日韩字符(U+0800–U+FFFF):3 字节
- 增补字符(U+10000–U+10FFFF):4 字节
一个关键设计特点:多字节序列的首字节以 110、1110 或 11110 开头(表示总字节数为 2、3 或 4),而后续字节始终以 10 开头。这使得 UTF-8 自同步——即使从流中间开始,你也能找到字符边界。
UTF-16:BMP 定长,其余变长
UTF-16 对基本多语言平面(BMP,U+0000–U+FFFF)内的字符使用 2 字节,对其他字符使用 4 字节(代理对)。它常用于 Java、.NET 和 Windows 内部。但它不兼容 ASCII——ASCII 字符变成 2 字节,带有一个前导零字节,使英文文本的存储翻倍。
文本如何变成二进制:完整示例
让我们逐步将字符串 "Hi 中" 转换为二进制。
确定 Unicode 码位:
H→ U+0048i→ U+0069(空格)→ U+0020中→ U+4E2D
以 UTF-8 编码每个码位:
- U+0048(0x48)在 ASCII 范围内 → 1 字节:
0100 1000 - U+0069(0x69)→ 1 字节:
0110 1001 - U+0020(0x20)→ 1 字节:
0010 0000 - U+4E2D(0x4E2D)在 3 字节范围内 → 3 字节:
- 码位的二进制:
0100 1110 0010 1101(16 位) - UTF-8 3 字节模板:
1110xxxx 10xxxxxx 10xxxxxx - 填充后:
1110 0100 1011 1000 1010 1101→ 十六进制:E4 B8 AD
- 码位的二进制:
- U+0048(0x48)在 ASCII 范围内 → 1 字节:
连接所有字节:
0100 1000 0110 1001 0010 0000 1110 0100 1011 1000 1010 1101
你可以使用我们的文本转二进制工具验证这个结果。
常见陷阱
- 混淆编码和代码页: 以 GBK 保存的文件用 UTF-8 读取会产生乱码(例如“锟斤拷”)。始终要知道源编码。
- 假设 ASCII 就够用: 非英文文本如果被截断为 7 位或将多字节序列当作单字符处理,会被损坏。
- 混淆 Unicode 和 UTF-8: Unicode 定义码位;UTF-8 是存储方式之一。它们不可互换。
- 字节顺序标记(BOM): UTF-16 文件通常以 BOM(
U+FEFF)开头指示字节序。某些工具在 UTF-8 中遇到 BOM 会出错。 - char 类型的符号性: 在 C/C++ 中,
char默认可能是有符号或无符号的。在比较或算术运算前应转换为unsigned char,以避免符号扩展问题。
何时使用哪种编码
| 场景 | 推荐编码 | 原因 |
|---|---|---|
| 网页、API、JSON | UTF-8 | 通用、兼容 ASCII、自同步 |
| 内部 Windows 应用 | UTF-16 | Windows API 原生、BMP 字符处理快 |
| 遗留中文系统 | GBK | 中文文本紧凑,但新项目应避免 |
| 嵌入式系统 | UTF-8 | 对以 ASCII 为主的日志节省空间 |
| 跨平台文件 | 无 BOM 的 UTF-8 | 跨操作系统兼容性最佳 |
常见问题
ASCII 和 Unicode 有什么区别?
ASCII 是一种 7 位编码,覆盖 128 个英文字符。Unicode 是一个更大的字符集(超过 14 万个字符),为所有书写系统的每个字符分配唯一的码位。ASCII 是 Unicode 的子集(U+0000–U+007F)。
为什么 UTF-8 使用可变长度?
可变长度使 UTF-8 在支持完整 Unicode 范围的同时保持与 ASCII 的向后兼容(每个字符 1 字节)。像 UTF-32 这样的定长编码会浪费常见 ASCII 文本的空间。
如何检测文件的编码?
没有万无一失的方法,但你可以查找 BOM、分析字节模式(例如 UTF-8 验证)或使用启发式库如 chardet(Python)或 enca。为了可靠,始终将编码元数据与文件一起存储。
文本中出现“锟斤拷”是什么原因?
这是经典的乱码产物。当以 GBK(或 GB2312)编码的文件被当作 UTF-8 解码时,某些字节序列会产生替换字符,这些字符被重新编码后形成“锟斤拷”模式。这是一连串编码不匹配的结果。
UTF-8 总是最佳选择吗?
对于大多数现代应用——尤其是网页、云和跨平台——是的。UTF-8 对 ASCII 紧凑、支持所有 Unicode 字符,并且是 HTML、JSON 和许多编程语言的默认编码。例外包括大量 CJK 文本的系统(GBK 可能节省空间)或 UTF-16 是原生字符串格式的环境(如 Java、.NET 内部)。