首页/开发/正则与编码速查/UTF-8 变长编码原理与规则

UTF-8 变长编码原理与规则

UTF-8 是 Unicode 的变长编码:一个码位用 1 到 4 字节表示,前 128 个码位与 ASCII 逐位相同,首字节的位模式表明序列长度,因此具备自同步能力,是文件与网络传输的默认选择。

正则与编码速查开发更新于 2026-10-17
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​​‌‌​​​‌‌‌​​​​​‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌​​‌​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

UTF-8 的编码规则

UTF-8 把 Unicode 码位编码成 1 至 4 个字节:ASCII 区仍是单字节,拉丁扩展等用 2 字节,常用汉字用 3 字节,emoji 与增补平面字符用 4 字节。序列中首字节的高位连续的 1 表示总长度,后续字节一律以 10 开头,形成「前导字节 + 续字节」的结构。这个设计带来两个结果:ASCII 完全兼容,以及可以在字节流任意位置判断当前字节是首字节还是续字节,即自同步。UTF-8 本身没有字节序问题,因此不需要 BOM。

基本信息

编码长度1-4 字节,对应 U+0000 至 U+10FFFF
ASCII 兼容U+0000-U+007F 与 ASCII 逐位相同
自同步首字节表明长度,续字节以 10 开头,可快速定位字符边界
字节序与字节序无关,不需要也不能依赖 BOM
保留区U+D800-U+DFFF 代理码位不用于直接编码字符
典型用途文件存储、HTTP/JSON/HTML 默认编码、源码文件

典型使用场景

  • 新建项目统一编码:源码、配置、日志一律 UTF-8,消除跨平台差异
  • 接口与数据交换:JSON 默认 UTF-8,HTTP 正文与头部也都以它为主
  • 长度估算:按字节计算存储与带宽时,中文按 3 字节、emoji 按 4 字节估算
  • 乱码排查:判断一段字节是否为合法 UTF-8 序列,是定位编码问题的第一步
  • 跨系统迁移:从 GBK 系或 Latin-1 系迁移到 UTF-8 时做全量校验

字节层面观察

字节层面观察
python -c "print('A'.encode('utf-8'), '中'.encode('utf-8'))"   # A 为 1 字节,中为 3 字节
python -c "print(len('中文'), len('中文'.encode('utf-8')))"        # 字符数 2,字节数 6
python -c "print([bin(b) for b in '中'.encode('utf-8')])"          # 看首字节 1110 开头、续字节 10 开头
printf '中' | xxd                                                  # 直接观察十六进制字节
iconv -f UTF-8 -t UTF-8 file.txt > /dev/null && echo valid        # 非法序列会被 iconv 报出
file --mime-encoding file.txt                                      # 辅助判断实际编码

首字节与长度对照

首字节位模式字节数码位范围典型字符
0xxxxxxx1U+0000-U+007F英文、数字、ASCII 标点
110xxxxx2U+0080-U+07FF拉丁扩展、希腊、西里尔字母
1110xxxx3U+0800-U+FFFF中日韩常用汉字、全角符号
11110xxx4U+10000-U+10FFFFemoji、增补平面汉字
10xxxxxx续字节不单独成立出现在首字节之后,单独出现即非法
「一个字符几个字节」只是统计口径问题:UTF-8 里汉字 3 字节、emoji 4 字节,而 UTF-16 里汉字 2 字节、emoji 4 字节。字段长度限制、数据库列宽度、API 限流都要明确是按字节、按码位还是按字形簇计算。
截断 UTF-8 字节流是最常见的脏数据来源:按固定字节长度切分会切断多字节序列,尾部出现非法字节,解码时报错或被替换为问号,且原始字符无法还原。截断必须按字符边界进行。
MySQL 里的 utf8 与 utf8mb4 不是一回事:前者最多 3 字节,无法保存 emoji 与增补平面字符;需要完整 Unicode 支持时必须用 utf8mb4。类似的历史命名差异在其他系统里也存在,建库建表前要确认具体含义。

易错点

  • 按字节长度截断字符串:切断汉字或 emoji 的字节序列,产生非法 UTF-8 与替换字符 → 按字符切分,或至少回退到合法边界
  • 假设「一个汉字恒为 3 字节」:增补平面汉字是 4 字节,缓冲区按 3 字节估算会溢出或截断 → 按最坏 4 字节预留空间
  • 用带 BOM 的 UTF-8 文件喂给只认无 BOM 的解析器:首行出现不可见字符导致解析失败 → 保存时选择「UTF-8 无 BOM」
  • 把 UTF-8 与 Unicode 混为一谈:Unicode 是字符集,UTF-8 是它的编码方式之一 → 讨论问题时区分「码位」与「字节」两个层面
  • 在 MySQL 的 utf8 列里写 emoji:报错或被截断成问号 → 改用 utf8mb4 并同步调整连接编码

数据来源与参考

  • RFC 3629:UTF-8, a transformation format of ISO 10646
  • Unicode 官方:UTF-8 编码规则与最佳实践
  • WHATWG Encoding Standard:UTF-8 编码定义

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/regex/utf8-encoding-principle.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌‌‌​‌‌​​‌​‌​‌‌‌‌​​​​​‌​‌‌‌‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​​‌‌​​​‌‌‌​​​​​‌​‌‌​‌​‌‌​​‌​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​​‌​​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​​‌​‌‌​‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌​​‌​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​‌​‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​