在计算机中,字符的表示和存储是一个基础而重要的问题。为了支持全球各种语言的字符,我们需要一个统一的编码系统。Unicode 提供了这样的字符集,而 UTF-8、UTF-16、UTF-32 则是 Unicode 的不同编码实现方式。
✅ 一句话总结
Unicode 是字符集,定义了全球字符的唯一编号;UTF-8、UTF-16、UTF-32 是编码方式,用于将 Unicode 字符集中的字符转换为计算机可以存储和传输的二进制形式。它们各有优缺点,适用于不同场景。
✅ 一、Unicode:统一码(字符集)
🔹 什么是 Unicode?
- Unicode 是一个字符集(Character Set),它为世界上几乎所有语言的每一个字符分配了一个唯一的编号,称为码点(Code Point)。
- 例如:汉字“马”的 Unicode 码点是
U+9A6C。 - Unicode 的目标是替代传统的字符编码(如 ASCII、GBK、ISO-8859-1 等),实现全球统一编码。
🔹 Unicode 的编码空间
- Unicode 的编码空间分为 17 个平面(Planes):
- 第 0 平面(基本多语言平面 BMP):
U+0000 ~ U+FFFF - 第 1~16 平面(辅助平面):
U+10000 ~ U+10FFFF
- 第 0 平面(基本多语言平面 BMP):
- 每个平面有 65536 个字符,总共可以表示 1,114,112 个字符。
✅ 二、UTF-8:变长编码,最常用
🔹 定义:
- UTF-8 是 Unicode 的一种可变长度编码方式,每个字符可以使用 1~4 个字节 来表示。
- 它完全兼容 ASCII(ASCII 字符只占 1 个字节)。
🔹 编码规则:
| Unicode 编码范围 | UTF-8 编码格式(二进制) |
|---|---|
U+0000 - U+007F (0-127) | 0xxxxxxx |
U+0080 - U+07FF (128-2047) | 110xxxxx 10xxxxxx |
U+0800 - U+FFFF (2048-65535) | 1110xxxx 10xxxxxx 10xxxxxx |
U+10000 - U+10FFFF (65536-1114111) | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
🔹 示例:汉字“马”(U+9A6C)
- Unicode 码点:
0x9A6C(十进制:39532) - 属于第三范围(3 字节编码)
- 转换为二进制:
1001 1010 0110 1100 - 填入格式:
11101001 10101001 10101100 - 对应十六进制:
E9 A9 AC,即 UTF-8 编码为0xE9A9AC
🔹 特点:
- ✅ 空间效率高,尤其适合英文为主的文本;
- ✅ 向后兼容 ASCII;
- ✅ 网络传输首选(HTML、JSON、HTTP 等默认使用 UTF-8);
- ❌ 解析复杂,容错性差(某字节损坏可能影响后续字符);
✅ 三、UTF-16:变长编码,适合中文等语言
🔹 定义:
- UTF-16 也是一种可变长度编码方式,使用 2 或 4 个字节 表示一个字符。
- 基本平面字符(
U+0000 - U+FFFF)使用 2 个字节; - 辅助平面字符(
U+10000 - U+10FFFF)使用 4 个字节(代理对)。
🔹 代理对(Surrogate Pair)
- 基本平面中有一段保留区域
U+D800 - U+DFFF不表示任何字符; - UTF-16 利用这段空间来表示辅助平面字符:
- 高位代理(High Surrogate):
U+D800 - U+DBFF - 低位代理(Low Surrogate):
U+DC00 - U+DFFF
- 高位代理(High Surrogate):
🔹 示例:字符“𡠀”(U+21800)
- 码点:
0x21800 - 减去偏移:
0x21800 - 0x10000 = 0x11800 - 转为 20 位二进制:
0001000110 0000000000 - 高位:
0xD800 + 0001000110 = 0xD846 - 低位:
0xDC00 + 0000000000 = 0xDC00 - UTF-16 编码为:
0xD846 0xDC00
🔹 特点:
- ✅ 对中文等常用字符更节省空间(2 字节 vs UTF-8 的 3 字节);
- ✅ 支持所有 Unicode 字符;
- ❌ 编码逻辑复杂(代理对机制);
- ❌ 不兼容 ASCII;
- ❌ 无法从任意位置开始解析(需要知道字节顺序);
✅ 四、UTF-32:定长编码,最简单但最占空间
🔹 定义:
- UTF-32 是 Unicode 的一种固定长度编码方式,每个字符都占用 4 个字节。
- 它直接将 Unicode 码点转换为 32 位整数。
🔹 示例:汉字“马”(U+9A6C)
- Unicode 码点:
0x9A6C - UTF-32 编码为:
0x00009A6C(32 位二进制)
🔹 特点:
- ✅ 编码解码简单,无需处理变长;
- ❌ 存储空间占用大(英文字符也占 4 字节);
- ❌ 实际应用较少,主要用于内存处理;
✅ 五、总结对比表格
| 特性 | Unicode | UTF-8 | UTF-16 | UTF-32 |
|---|---|---|---|---|
| 类型 | 字符集(定义字符) | 编码方式 | 编码方式 | 编码方式 |
| 编码长度 | - | 1~4 字节 | 2 或 4 字节 | 固定 4 字节 |
| 是否兼容 ASCII | - | ✅ 是 | ❌ 否 | ❌ 否 |
| 空间效率 | - | 英文最优 | 中文最优 | 最差 |
| 编码复杂度 | - | 中等 | 复杂(代理对) | 最简单 |
| 应用场景 | - | 网络传输、JSON、HTML | Windows、Java、JavaScript | 内存操作、内部处理 |
| 容错能力 | - | 弱(影响后续字符) | 强(仅影响当前字符) | 强 |
✅ 六、一句话总结
Unicode 是字符集,UTF-8、UTF-16、UTF-32 是其不同的编码方式。UTF-8 在网络传输中占主导地位,UTF-16 适合处理中文等非英文字符,UTF-32 虽然简单但占用空间大,主要用于内部处理。
💡 进阶建议
- 网络传输、前端开发首选 UTF-8;
- Java、JavaScript 内部使用 UTF-16;
- UTF-32 用于需要快速访问字符的场景(如图形渲染);
- 处理 Emoji、古文字等辅助平面字符时需注意代理对问题;
- 使用
Buffer、TextEncoder、TextDecoder等 API 进行编码转换;