Unicode编码UTF-8、UTF-16、UTF-32的区别
Unicode 基本概念
Unicode 是一个国际标准,为世界上几乎所有的文字系统中的每个字符分配了唯一的数字标识(码点)。Unicode 编码空间从 U+0000
到 U+10FFFF
,共有 1,114,112 个码点,分为17个平面:
- 基本多语言平面(BMP):
U+0000
-U+FFFF
- 16个辅助平面:
U+10000
-U+10FFFF
主要 Unicode 编码方式
1. UTF-8
变长编码,使用1-4个字节。
特点:
- 兼容 ASCII
- 节省空间
- 自同步能力强
- 没有字节序问题
编码规则:
- 1字节:
0xxxxxxx
(ASCII 字符) - 2字节:
110xxxxx 10xxxxxx
(拉丁文扩展、希腊文等) - 3字节:
1110xxxx 10xxxxxx 10xxxxxx
(中日韩文字等) - 4字节:
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
(表情符号、古文字等)
- 1字节:
使用场景:
- Web 页面(HTML5 默认编码)
- 文件存储
- 网络传输
- Linux/Unix 系统
- 跨平台应用
2. UTF-16
变长编码,使用2或4个字节。
特点:
- 基本平面字符使用2字节
- 辅助平面字符使用4字节(代理对)
- 有字节序问题(需要 BOM 标记)
编码规则:
- 基本平面:直接使用码点值
- 辅助平面:使用代理对
- 高代理:
(码点 - 0x10000) / 0x400 + 0xD800
- 低代理:
(码点 - 0x10000) % 0x400 + 0xDC00
- 高代理:
使用场景:
- Windows 操作系统内部
- JavaScript 内部字符串表示
- Java 字符串
- .NET 框架
- 许多编程语言的内部表示
3. UTF-32
固定长度编码,使用4个字节。
特点:
- 最简单的编码方式
- 直接使用码点值
- 有字节序问题
- 空间效率低
编码规则:
- 直接使用码点值,不足补0
使用场景:
- 需要随机访问字符的场景
- 某些 Unix 系统
- 某些编程语言的内部处理
- 字符处理算法
4. GB18030
中国国家标准,兼容 GB2312 和 GBK。
特点:
- 兼容 ASCII
- 可表示所有 Unicode 字符
- 变长编码(1、2或4字节)
使用场景:
- 中国政府系统
- 某些需要符合中国标准的软件
5. Shift-JIS
日本编码标准。
特点:
- 变长编码(1或2字节)
- 兼容 ASCII
使用场景:
- 日本本地软件
- 日语网站
6. ISO-8859 系列
欧洲语言的8位编码标准。
特点:
- 单字节编码
- 兼容 ASCII
- 不同语言有不同变种(如ISO-8859-1、ISO-8859-2等)
使用场景:
- 欧洲语言文档
- 老旧系统
编码示例对比
基本平面字符示例
以汉字"马"为例(位于基本平面):
Unicode 码点:U+9A6C (十进制:39532)
UTF-32BE: 00 00 9A 6C (4字节)
UTF-32LE: 6C 9A 00 00 (4字节)
UTF-16BE: 9A 6C (2字节)
UTF-16LE: 6C 9A (2字节)
UTF-8: E9 A9 AC (3字节)
GB18030: C2 ED (2字节)
辅助平面字符示例
以汉字"𡠀"为例(位于辅助平面):
Unicode 码点:U+21800 (十进制:137216)
UTF-32BE: 00 02 18 00 (4字节)
UTF-32LE: 00 18 02 00 (4字节)
UTF-16BE: D8 46 DC 00 (4字节,代理对)
UTF-16LE: 46 D8 00 DC (4字节,代理对)
UTF-8: F0 A1 A0 80 (4字节)
GB18030: 95 32 82 36 (4字节)
ASCII 字符示例
以字母"A"为例:
Unicode 码点:U+0041 (十进制:65)
UTF-32BE: 00 00 00 41 (4字节)
UTF-32LE: 41 00 00 00 (4字节)
UTF-16BE: 00 41 (2字节)
UTF-16LE: 41 00 (2字节)
UTF-8: 41 (1字节)
GB18030: 41 (1字节)
ISO-8859: 41 (1字节)
字节序(Byte Order)
对于多字节编码(如UTF-16和UTF-32),存在字节序问题:
- 大端序(Big Endian, BE):高位字节在前
- 小端序(Little Endian, LE):低位字节在前
为了标识字节序,常在文件开头添加字节序标记(BOM):
- UTF-8 BOM:
EF BB BF
(不必要但有时使用) - UTF-16BE BOM:
FE FF
- UTF-16LE BOM:
FF FE
- UTF-32BE BOM:
00 00 FE FF
- UTF-32LE BOM:
FF FE 00 00
编程语言中的 Unicode 处理
JavaScript
javascript
// 字符串内部使用UTF-16
const char = "𡠀";
console.log(char.length); // 2(代理对占用两个代码单元)
console.log(char.codePointAt(0)); // 137216
console.log("\u{21800}"); // 𡠀(ES6支持)
// 正确处理字符
console.log([...char].length); // 1
Python
python
# Python 3 字符串内部使用 Unicode
char = "𡠀"
print(len(char)) # 1(Python正确处理码点)
print(ord(char)) # 137216
print("\U00021800") # 𡠀
# 编码转换
utf8_bytes = char.encode('utf-8') # b'\xf0\xa1\xa0\x80'
utf16_bytes = char.encode('utf-16') # b'\xff\xfeF\xd8\x00\xdc'(带BOM)
Java
java
String char = "𡠀";
System.out.println(char.length()); // 2(Java使用UTF-16)
System.out.println(char.codePointCount(0, char.length())); // 1
System.out.println(Character.toCodePoint(
char.charAt(0), char.charAt(1))); // 137216
编码选择建议
Web开发:
- 使用 UTF-8,这是HTML5的默认编码
- 明确在HTML中声明:
<meta charset="UTF-8">
数据库:
- 推荐使用 UTF-8 或 UTF-8mb4(MySQL中支持表情符号)
- 注意字段长度设计
API和数据交换:
- 使用 UTF-8,这是JSON的标准编码
文件存储:
- 跨平台:UTF-8
- Windows专用:可考虑 UTF-16
- 谨慎使用BOM
内存处理:
- 随机访问需求高:考虑 UTF-32
- 内存受限:考虑 UTF-8