首页/开发/正则与编码速查/UTF-8 字节数与首字节规律

UTF-8 字节数与首字节规律

UTF-8 的字节数由首字节高位的连续 1 个数决定:0xxxxxxx 为 1 字节、110 开头为 2、1110 开头为 3、11110 开头为 4,续字节一律 10 开头;判定长度只需看首字节,这是流式解码与边界校验的基础。

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

首字节决定长度

UTF-8 把长度信息编码进了首字节:首字节以 0 开头说明是单字节 ASCII;以 110 开头说明还有 1 个续字节;1110 开头还有 2 个;11110 开头还有 3 个。续字节统一以 10 开头,因此看到 10 开头的字节就说明它属于前一个字符。这套规则让解码器无需从头扫描就能定位边界,也让校验器能识别非法序列(孤立续字节、过长编码、超出 U+10FFFF 的取值)。

基本信息

判定依据只看首字节的高位模式,不必读完整序列
首字节合法区间0x00-0x7F、0xC2-0xDF、0xE0-0xEF、0xF0-0xF4
续字节区间0x80-0xBF(一律以 10 开头)
非法首字节0x80-0xBF 单独出现、0xC0-0xC1、0xF5-0xFF
长度上限4 字节,对应码位上限 U+10FFFF
衍生校验读取长度后必须验证后续字节都在续字节区间内

典型使用场景

  • 流式解析:从字节流中判断当前字符占几个字节,避免半包时误判
  • 输入校验:快速拒绝非法 UTF-8 输入(畸形序列常被用于绕过安全过滤)
  • 固定长度字段裁剪:按客户端的字节上限裁剪前先回退到合法字符边界
  • 协议实现:自写解析器或做协议兼容测试时验证编码合法性
  • 性能优化:按字节扫描合法 ASCII 快速路径,遇到高位字节才进入多字节分支

位模式观察示例

位模式观察示例
python -c "b='中'.encode('utf-8'); print([hex(x) for x in b])"      # 三字节:E4 B8 AD
python -c "print([bin(x) for x in '中'.encode('utf-8')])"           # 11100100 / 10111000 / 10101101
python -c "print(len('𠀀'.encode('utf-8')))"                          # 增补平面字符为 4 字节
python - <<'EOF'
# 按首字节判断长度(简化演示,不含完整合法性校验)
for c in 'A中':
    b = c.encode('utf-8')[0]
    n = 1 if b < 0x80 else 2 if b < 0xE0 else 3 if b < 0xF0 else 4
    print(c, hex(b), n)
EOF
iconv -f UTF-8 -t UTF-16LE file.txt > /dev/null && echo sequence-ok  # 非法序列会失败

首字节区间判定表

首字节十六进制字节数说明
0x00-0x7F1ASCII,最高位为 0
0x80-0xBF非法续字节,不能出现在字符首位
0xC0-0xDF2其中 0xC0-0xC1 会产生过长编码,非法
0xE0-0xEF3覆盖 U+0800-U+FFFF,含常用汉字
0xF0-0xF44覆盖增补平面,0xF5-0xFF 超出合法范围
0xF5-0xFF非法超出 U+10FFFF,任何序列中都非法
过长编码(overlong)必须拒绝:用多余的字节写出一个本可用更少字节表示的码位属于非法序列。历史上攻击者利用它与过滤器的解码差异绕过安全校验,因此自己做校验时不要只看「字节数是否正确」,还要检查码位是否落在该长度对应的最小范围内。
不同语言对非法字节的默认处理不同:有的抛异常(严格模式),有的替换为 U+FFFD,有的原样保留字节。跨系统传递数据时,替换策略会让错误被静默吞掉,调试阶段建议先开启严格校验,确认数据干净后再决定线上策略。
长度不等于显示宽度:一个 3 字节汉字在终端通常占两个字符宽,一个 4 字节 emoji 可能占两格或按字形簇整体显示。做表格对齐与截断显示时要按显示宽度计算,而不是按字节数或码位数。

易错点

  • 把孤立续字节当独立字符:解析错位,后续整段内容乱码 → 解码前先做序列合法性校验
  • 接受过长编码:不同组件对同一序列解释不一致,可用于绕过黑名单 → 严格模式下拒绝所有非法与过长序列
  • 按字节数当字符数做校验:限长 10 的字段实际只能放 3 个汉字,体验与预期不符 → 明确长度口径并在接口文档写清
  • 半包时按固定长度解析:分包边界落在多字节序列中间,解析出非法字符 → 缓存未完整序列,凑齐后再解码
  • 忽略 BOM 的存在:某些工具写出的文件带 UTF-8 BOM,首字节不在 ASCII 区,解析首字符出错 → 读取前剥离 BOM 或按 BOM 感知方式打开

数据来源与参考

  • RFC 3629:UTF-8 编码与合法性约束(含过长编码)
  • Unicode 官方:UTF-8 编码形式与安全考虑
  • WHATWG Encoding Standard:UTF-8 解码器行为

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

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