跳到主要内容

UTF-8 字节数到底怎么算:中文为什么比英文占更多字节

讲清楚 UTF-8 字节数和字符数的区别:英文 1 字节,中文 3 字节,emoji 4 字节。带一个中英混排的真实例子,帮你算准数据库字段长度和接口长度上限,别再让非英文文本悄悄溢出。

发布于 作者 李雷
#UTF-8 #字节数 #编码 #数据库 #字符串

UTF-8 字节数到底怎么算:中文为什么比英文占更多字节

写后端的人迟早会撞上同一个坑:前端校验通过的一个名字,插进数据库却报「value too long」。明明数着才几个字,怎么就超了?问题几乎都出在同一个误会上,把字符数当成了字节数。这两个数在纯英文里相等,可一旦混进中文或 emoji 就分家了,而存储和接口看的恰恰是后者。

字符数和字节数是两回事

字符是给人数的单位,你看屏幕上有几个符号,它就是几。字节是机器存的单位,一段文本写进文件、发上网络、落进数据库,占多少磁盘和带宽,算的都是字节。

UTF-8 是一种变长编码,不同字符占的字节数不一样:

  • 英文字母、数字、半角标点这类 ASCII 字符,1 个字节。
  • 拉丁文带重音的字符,比如 café 里的 é,2 个字节。
  • 绝大多数汉字以及日文韩文等 CJK 字符,3 个字节。
  • 大多数 emoji,4 个字节,因为它们落在 U+FFFF 之上的星光面。

所以「字符数」和「字节数」从来不是一个口径。你可以用 字符串字节数统计 把一段文本同时数出 UTF-8 字节、UTF-16 码元、Unicode 码点和字符数,一眼看清它们在哪儿对不上。

中文为什么占 3 个字节

根子在 UTF-8 的设计。ASCII 那 128 个字符沿用单字节,最高位是 0,这样老的纯英文文本不用改就能直接当 UTF-8 读。剩下的字符就得用多字节序列表示,字节越靠后的字符,需要的字节越多。

汉字在 Unicode 里的码点大多落在 U+4E00 到 U+9FFF 这一段,这个区间的码点用 UTF-8 编码正好需要 3 个字节。拿「中」举例,它的码点是 U+4E2D,编码后的字节序列是 e4 b8 ad,实打实 3 个字节。这不是某个数据库的特殊设定,是 UTF-8 标准本身决定的,换哪个系统都一样。

emoji 更靠后。咧嘴笑脸 😀 的码点是 U+1F600,已经超过 U+FFFF,UTF-8 要用 4 个字节(f0 9f 98 80)才装得下。再算上组合 emoji,情况更夸张:👨‍👩‍👧 这种家庭 emoji 是用零宽连接符把好几个码点拼起来的,屏幕上看着是一个图,实际可能占 18 个甚至更多字节。

一个中英混排的真实例子

来看一段我经常拿来测的字符串:Hi 张三 👋

逐项拆开数:

  • Hi,2 个英文字母加中间 1 个空格,3 个 ASCII 字符,各 1 字节,共 3 字节。
  • 张三,2 个汉字,每个 3 字节,共 6 字节。
  • 末尾再加 1 个空格,1 字节。
  • 👋 挥手 emoji,1 个码点,4 字节。

字符数这边:Hi(含空格)3 个 + 张三 2 个 + 空格 1 个 + emoji 1 个 = 7 个字符。 字节数这边:3 + 6 + 1 + 4 = 14 个 UTF-8 字节。

7 个字符,14 个字节,整整差一倍。如果还按 UTF-16 的 .length 去数,那个 emoji 又会被算成 2 个码元(代理对),于是 .length 给出 8。同一段文本三个数字三个口径,谁也不等于谁。

数据库字段和接口为什么按字节卡

数据库在磁盘上存的是编码后的形态,所以很多场景下 VARCHAR 的长度是按字节算的。PostgreSQL、旧版 MySQL 的 utf8 字符集,还有大量定长缓冲区,给的都是字节预算,不是字符预算。

这意味着一个 VARCHAR(20)、限 20 字节的姓名字段:

  • 能放 20 个英文字母。
  • 只够放约 6 个汉字(6 × 3 = 18 字节)。
  • 5 个 4 字节 emoji 就把它填满了。

接口和协议同理。短信段、二进制协议的定长字段、不少聊天 API,卡的都是编码后的大小,不是你眼里看到的字符数。按字符数瞎裁,很容易在边界处把一个 3 字节或 4 字节的多字节序列从中间切断,留下一串乱码。正确做法是裁之前先按字节数判断,插入或发送前用 UTF-8 字节数预估一下到底塞不塞得下。

几条记在心里的判断

我自己踩过这些坑之后,总结成几句话:

  • 校验长度别只用 .length,它返回的是 UTF-16 码元数。一个 emoji 算 2,140 字的上限可能拒掉用户以为远没到 140 的文本。
  • 定存储和网络上限,永远按字节,别按字符数。10 个汉字看着是 10,实际占 30 字节。
  • 一个 emoji 不一定是一个码点。带连接符的组合 emoji 可能是好几个码点、十几个字节。

如果你想顺手把字节数换算成更直观的 KB,可以接着用 存储单位换算 把字节、KB、MB 之间的关系一并理清。先把字节这一关算准,后面的字段长度和接口上限就不会再无声无息地溢出。


Made by Toolora · Updated 2026-06-13