RFC 3629 - UTF-8, a transformation format of ISO 10646
UTF-8, ISO 10646的转换格式
发布日期: 2003年11月
状态: 互联网标准 (STD 63)
作者: F. Yergeau (Alis Technologies)
废止: RFC 2279
类别: Standards Track
摘要 (Abstract)
ISO/IEC 10646-1定义了一个称为通用字符集 (Universal Character Set, UCS) 的大型字符集,涵盖了世界上大多数书写系统。然而,最初提出的UCS编码与许多当前应用程序和协议不兼容,这导致了UTF-8的开发,即本备忘录的主题。UTF-8的特点是保留完整的US-ASCII范围,提供与依赖US-ASCII值但对其他值透明的文件系统、解析器和其他软件的兼容性。本备忘录废止并替代RFC 2279。
本备忘录的状态 (Status of this Memo)
本文档为互联网社区规定了一个互联网标准跟踪协议,并请求讨论和改进建议。有关本协议的标准化状态和地位,请参阅当前版本的"互联网官方协议标准" (STD 1)。本备忘录的分发不受限制。
版权声明 (Copyright Notice)
Copyright (C) The Internet Society (2003). All Rights Reserved.
目录 (Table of Contents)
主要章节
- 1. Introduction (简介)
- 2. Notational conventions (符号约定)
- 3. UTF-8 definition (UTF-8定义)
- 4. Syntax of UTF-8 Byte Sequences (UTF-8字节序列语法)
- 5. Versions of the standards (标准版本)
- 6. Byte order mark (BOM) (字节顺序标记)
- 7. Examples (示例)
- 8. MIME registration (MIME注册)
- 9. IANA Considerations (IANA考虑)
- 10. Security Considerations (安全考虑)
- 11. Acknowledgements (致谢)
- 12. Changes from RFC 2279 (自RFC 2279以来的变更)
- 13. Normative References (规范性参考文献)
- 14. Informative References (信息性参考文献)
为什么UTF-8很重要?
UTF-8是现代互联网的标准字符编码,几乎所有现代Web应用、API和数据格式都使用UTF-8。
核心优势
| 特性 | 说明 | 重要性 |
|---|---|---|
| ASCII兼容 | ASCII字符编码完全相同 | ⭐⭐⭐⭐⭐ |
| 无字节序问题 | 没有大小端问题 | ⭐⭐⭐⭐⭐ |
| 自同步 | 可从任意位置开始解码 | ⭐⭐⭐⭐ |
| 空间效率 | 英文1字节,中文3字节 | ⭐⭐⭐⭐ |
| 全球支持 | 支持所有Unicode字符 | ⭐⭐⭐⭐⭐ |
UTF-8编码规则快速参考
编码表
Unicode范围 字节数 UTF-8字节模式
─────────────────────────────────────────────
U+0000 - U+007F 1 0xxxxxxx
U+0080 - U+07FF 2 110xxxxx 10xxxxxx
U+0800 - U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
U+10000 - U+10FFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
字符范围覆盖
1字节 (ASCII):
- 拉丁字母、数字、基本标点
- 控制字符
- 范围: U+0000 - U+007F
2字节:
- 拉丁扩展
- 希腊文、西里尔文、阿拉伯文、希伯来文
- 范围: U+0080 - U+07FF
3字节:
- 中日韩文字(CJK)
- 大部分其他语言文字
- 范围: U+0800 - U+FFFF
4字节:
- Emoji表情符号
- 历史文字、罕用汉字
- 范围: U+10000 - U+10FFFF
编码示例
ASCII字符
字符: 'A'
Unicode: U+0041
二进制: 0100 0001
UTF-8: 0x41
字节数: 1
编码过程:
U+0041 < U+007F → 使用1字节模板
0xxxxxxx → 01000001 → 0x41
中文字符
字符: '你'
Unicode: U+4F60
二进制: 0100 1111 0110 0000
UTF-8: 0xE4 0xBD 0xA0
字节数: 3
编码过程:
U+4F60在U+0800-U+FFFF范围 → 使用3字节模板
1110xxxx 10xxxxxx 10xxxxxx
↓ ↓ ↓
0100 111101 100000
↓ ↓ ↓
11100100 10111101 10100000
0xE4 0xBD 0xA0
Emoji表情
字符: '😀'
Unicode: U+1F600
二进制: 0001 1111 0110 0000 0000 0000
UTF-8: 0xF0 0x9F 0x98 0x80
字节数: 4
编码过程:
U+1F600在U+10000-U+10FFFF范围 → 使用4字节模板
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
↓ ↓ ↓ ↓
000011 111101 100000 000000
↓ ↓ ↓ ↓
11110000 10011111 10011000 10000000
0xF0 0x9F 0x98 0x80
UTF-8的独特特性
1. ASCII兼容性
ASCII文件 = 有效的UTF-8文件
示例:
Hello World (ASCII)
同时也是有效的UTF-8
原因:
ASCII使用7位 (0xxxxxxx)
UTF-8的1字节形式就是ASCII
2. 自同步 (Self-Synchronizing)
UTF-8字节流:
... E4 BD A0 E5 A5 BD ...
你 好
从任意位置开始:
- 首字节 (1110xxxx 或 110xxxxx 或 11110xxx) 标识字符开始
- 后续字节 (10xxxxxx) 绝不会被误认为首字节
示例:
E4 BD A0 E5 A5 BD
↑ ↑
从这里开始可以识别出这是后续字节
从这里开始可以识别出新字符
3. 无字节序问题
UTF-16需要BOM:
FE FF ... (Big Endian)
FF FE ... (Little Endian)
UTF-8不需要:
字节顺序固定,从高到低
无需BOM指示字节序
常见应用
Web开发
<!-- HTML文件 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>UTF-8示例</title>
</head>
<body>
<p>你好,世界! Hello, World! 😀</p>
</body>
</html>
HTTP协议
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
<!DOCTYPE html>...
JSON数据
{
"name": "张三",
"message": "Hello 世界",
"emoji": "😀"
}
数据库
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
安全考虑要点
⚠️ 非最短形式攻击
禁止使用过长编码:
正确: 'A' → 0x41 (1字节)
错误: 'A' → 0xC0 0x81 (2字节,过长)
'A' → 0xE0 0x80 0x81 (3字节,过长)
危险:
过长编码可能绕过安全检查
例如: 路径遍历 "../" 的过长编码
⚠️ 无效序列
必须拒绝:
- 孤立的后续字节 (10xxxxxx)
- 超出Unicode范围 (>U+10FFFF)
- UTF-16代理对 (U+D800-U+DFFF)
- 截断的多字节序列
编程语言支持
Python
# 编码
s = "你好世界"
b = s.encode('utf-8') # bytes对象
# 解码
s = b.decode('utf-8') # str对象
# 文件操作
with open('file.txt', 'r', encoding='utf-8') as f:
content = f.read()
JavaScript
// 编码
const str = "你好世界";
const encoder = new TextEncoder();
const bytes = encoder.encode(str); // Uint8Array
// 解码
const decoder = new TextDecoder('utf-8');
const text = decoder.decode(bytes); // string
Java
// 编码
String str = "你好世界";
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
// 解码
String decoded = new String(bytes, StandardCharsets.UTF_8);
// 文件操作
Files.readString(path, StandardCharsets.UTF_8);
Go
// Go的string原生就是UTF-8
s := "你好世界"
// 转换为字节切片
b := []byte(s)
// 从字节切片转换
s = string(b)
性能特性
空间效率对比
| 文本类型 | UTF-8 | UTF-16 | UTF-32 |
|---|---|---|---|
| 英文 | 1字节 | 2字节 | 4字节 |
| 中文 | 3字节 | 2字节 | 4字节 |
| Emoji | 4字节 | 4字节 | 4字节 |
英文为主的文本: UTF-8最优
中日韩为主的文本: UTF-16略优
混合文本: UTF-8通常最优
相关资源 (Related Resources)
- 官方原文: RFC 3629 (TXT)
- 官方页面: RFC 3629 DataTracker
- 标准: STD 63
- 废止: RFC 2279
- Unicode标准: Unicode.org
- ISO 10646: ISO/IEC 10646
快速诊断工具
识别UTF-8编码
def is_utf8(data):
"""检测数据是否为有效UTF-8"""
try:
data.decode('utf-8')
return True
except UnicodeDecodeError:
return False
修复编码问题
# 常见问题: 双重编码
# 原始: "你好"
# 错误显示: "ä½ å¥½"
# 修复方法:
text = "ä½ å¥½"
fixed = text.encode('latin1').decode('utf-8')
# 结果: "你好"
重要提示: UTF-8是现代互联网的默认标准。始终使用UTF-8编码,避免使用遗留编码如GBK、ISO-8859-1、Windows-1252等。所有新项目都应该使用UTF-8作为唯一的字符编码。