字节计数器
粘贴文本以查看其在 UTF-8、UTF-16 和 ASCII 中的字节大小。非常适合检查数据库列的限制。
结果
工作原理
- 输入或粘贴文本: 在输入框中输入或粘贴任意文本。
- 查看字节计数: 该工具会即时并排显示 UTF-8、UTF-16、ASCII 及其他编码下的字节数。
- 检查限制: 将字节数与常见限制(SMS:160 字符,HTTP 头:8 KB,数据库字段等)进行比较,查看您的内容是否合适。
为什么要使用字节计数器?
字符数和字节数并不相同。一个表情符号在 UTF-8 中可能占 4 个字节。中文和阿拉伯文字符每个占 2-3 个字节。许多系统强制执行的是字节限制,而不是字符限制,包括 MySQL VARCHAR 字段、Redis 值、HTTP 头、SMS 消息和云存储对象名。字节计数器会显示您的文本在每种编码下的实际字节大小,以便您保持在系统约束范围内。
功能
- 多种编码大小: 显示 UTF-8、UTF-16 LE/BE、UTF-32 和 Latin-1 的字节数。
- 字符细分: 分别统计总字符数、Unicode 代码点和多字节字符。
- 常见限制预设: 与 SMS(160)、tweet(280)、meta 描述(160)、MySQL VARCHAR 限制等进行比较。
- 实时更新: 字节数随您输入实时更新。
- 编码比较: 查看哪种编码对您的特定文本最为紧凑。
常见问题
为什么我的字节数大于字符数?
许多字符在 UTF-8 中占用超过 1 个字节。ASCII 字符(A-Z、0-9、标点符号)每个占 1 字节。拉丁扩展字符(带重音的字母)占 2 字节。中文、日文、韩文和阿拉伯文字符通常占 3 字节。表情符号通常占 4 字节。
大多数网络系统使用什么编码?
UTF-8 是网络内容、API、JSON 和数据库的主导编码。MySQL 和 PostgreSQL 默认使用 UTF-8。在检查字节限制时,除非您的系统另有规定,否则请使用 UTF-8 列。
为什么 SMS 消息有 160 字符的限制?
传统 SMS 使用 7 位 GSM 编码,每段允许 160 个字符。当您包含任何非 GSM 字符(如智能引号、表情符号或非拉丁字母)时,消息会切换到 UCS-2 编码,每段的限制降至 70 个字符。
字节到底是什么?
一个字节是 8 位,可以容纳 256 个不同的值。在文本中,这 256 个值通过编码映射到字符,编码是一本规则手册,规定「这个字节序列等于这个字符」。同一个字节串在不同编码下可能表示完全不同的文本:字节 0xE9 在 Latin-1 中是「é」,在 UTF-8 中是 3 字节序列的开头,或者是 UTF-16 编码单元的一部分。编码就是全部的故事。
当你把文本保存到磁盘、通过网络发送或存储到数据库时,实际持久化的是字节,不是字符。文本编辑器里看到的字符数是在显示时计算的,在字节被解码之后。如果两边的编码不匹配,你就会得到乱码(mojibake):用错误编码解码的文本会显示为乱七八糟的字符(经典的 é 而不是 é,就是当 Windows-1252 的字节被当作 UTF-8 读取时发生的)。
字节计数才是数据库列限制、HTTP 头缓冲区、SMS 负载和云存储对象键所衡量的,不管文本「看起来」如何。这个计数器报告四种你最可能关心的编码的字节大小:UTF-8(现代默认)、UTF-16(Windows / Java / JavaScript 内部格式)、ASCII(仅对英语拉丁文本有效)和 Latin-1(单字节遗留回退)。旁边的字符数作为参考。
UTF-8:故事
UTF-8 由 Ken Thompson 和 Rob Pike 在贝尔实验室,1992 年 9 月 2 日晚上设计草稿,据说是在新泽西州一家餐馆的餐垫上写的,当时 Plan 9 团队需要一种 ASCII 兼容的可变长度 Unicode 编码。设计具有几乎没有其他编码同时具备的三个属性:ASCII 文本也是有效的 UTF-8(每个字符 1 字节,字节相同)、编码是自同步的(任何字节的高位告诉你它是开始一个新字符还是延续一个现有字符)、没有字节序歧义。这三个属性合在一起解释了 UTF-8 为什么在网络上取代了所有竞争编码。
它首先标准化为 RFC 2044(1996 年 10 月),修订为 RFC 2279(1998 年 1 月),并被当前的 RFC 3629(2003 年 11 月)取代,该 RFC 将 UTF-8 限制为每字符最多 4 字节,以匹配 Unicode 最终的码位上限 U+10FFFF。W3Techs 自 2010 年起持续跟踪公共网络上的编码使用情况;UTF-8 从 2011 年的 56% 网站上升到大约 2026 年的 98%。HTML5 规范要求新内容使用 UTF-8;HTTP/2 和 HTTP/3 通过 HPACK / QPACK 发送 UTF-8 头部;RFC 8259 要求系统之间的 JSON 交换使用 UTF-8。如果你必须为所有用途选择一种编码,过去 15 年的答案一直是 UTF-8,未来 15 年的答案也将相同。
UTF-8 是可变长度,每字符 1 到 4 字节:
| 码位范围 | 字节 | 典型内容 |
|---|---|---|
| U+0000 – U+007F | 1 | ASCII 字母、数字、常用标点 |
| U+0080 – U+07FF | 2 | 拉丁扩展(é、ñ)、希腊文、西里尔文、阿拉伯文、希伯来文 |
| U+0800 – U+FFFF | 3 | 大多数 CJK 表意文字、天城文、泰文、谚文、€ 符号 |
| U+10000 – U+10FFFF | 4 | 表情符号、补充 CJK、历史文字 |
实际后果:UTF-8 中的英文文本平均每字符约 1 字节;中文约 3 字节;表情符号密集的消息每个可见字符可达 4 字节,组合表情符号(家庭 ZWJ 序列)看起来像一个字符却轻松达到 20-30 字节。
UTF-16 和代理对陷阱
UTF-16 是 Windows NT(1993)、Java 1.0(1996)、JavaScript(1995)、.NET 和 Mac OS X Cocoa NSString 选用的编码。它对基本多语言平面(U+0000 – U+FFFF)中的每个字符使用 2 字节,对其他所有字符使用代理对:一个高代理(D800–DBFF)加一个低代理(DC00–DFFF),共 4 字节。UTF-16 在磁盘上需要字节序标记(BOM)来区分大端(UTF-16BE,FE FF)和小端(UTF-16LE,FF FE);Windows 默认小端。
陷阱:在 JavaScript 中,"😀".length === 2。MDN 直接表明:length 属性「包含字符串的长度,以 UTF-16 编码单元为单位」。这就是为什么像 😄 这样的单个表情符号报告长度为 2(它位于补充平面,需要代理对),而家庭 ZWJ 序列 👨👩👧👦 报告长度为 11(四个 2 编码单元的表情符号加三个零宽度连接符)。同一个单字符家庭表情符号在 JavaScript 中算作 11,在 Python 3 中算作 5,在 Swift 中算作 1,具体取决于每种语言的字符串模型。在 JavaScript 中获得正确的可见字符数,请使用具有字素粒度的 Intl.Segmenter(自 2021 年起的每个常青树浏览器)。
ASCII、Latin-1 和 Unicode 之前的混乱
ASCII(美国信息交换标准代码)标准化为 ASA X3.4-1963,修订为 X3.4-1968,再次修订为 ANSI X3.4-1986。7 位代码,128 个字符:95 个可打印加 33 个控制。33 个控制字符包括 BEL、BS、CR、LF、DEL 等电传打字机遗产,以及在现代协议中幸存下来的几个(NUL、TAB、LF、CR、ESC)。ASCII 仍然作为 UTF-8 的严格子集工作,这就是为什么「纯 ASCII 文本」也是有效的 UTF-8,以及为什么对纯英语系统迁移到 UTF-8 是无痛的。
Latin-1 / ISO-8859-1(1987)是一个 256 字符的单字节扩展,增加了西欧重音字母、货币符号和常用标点。它是 1995 年至 2008 年左右 UTF-8 取代它之前西方网络内容的事实编码。Windows-1252 是 Microsoft 的 Latin-1 超集,在 C1 控制范围(0x80-0x9F)中增加了「智能引号」、长破折号和欧元符号;当 CSV 文件在 Mac 和 Windows 之间通过电子邮件发送时,这就是当一方将 Windows-1252 字节读作 UTF-8 时产生经典 é 乱码的源头。
MySQL「utf8」陷阱
自版本 4.1 以来,MySQL 有一个臭名昭著的字符集缺陷:utf8 字符集别名实际上不是 UTF-8。它是一个最大 3 字节的子集,无法表示 U+FFFF 以上的字符,这意味着它无法存储表情符号或补充平面字符。在 utf8 列中插入「🎉」会产生「?」或错误,具体取决于 sql_mode。解决方案是 utf8mb4,在 MySQL 5.5.3(2010 年 3 月)中添加;MySQL 8.0(2018 年 4 月)使 utf8mb4 成为新默认。但 8.0 之前创建的模式通常仍默认使用 3 字节版本。如果你看到表情符号从用户输入中悄悄消失,这几乎总是原因。PostgreSQL 没有等效陷阱,它原生接受真正的 UTF-8。
SMS、GSM-7 和 160 字节负载
160 字符 SMS 限制可追溯到 1985 年 Friedhelm Hillebrand 的计算,他是 GSM 工作组的工程师,据说他坐在打字机前,打出随机句子,数到「大多数消息可以用 160 个字符或更少表达」。然后 160 被反推为适合 140 字节负载使用 7 位字母表(140 × 8 ÷ 7 = 160)。编码细节在 3GPP TS 23.038(最初是 GSM 03.38)中正式确定,它们至今仍然支配着 SMS 计费。
以字节计:单个 SMS 在线路上是 140 字节。使用 GSM-7 时是 160 字符;使用 UCS-2(一种 2 字节固定宽度编码,用于 GSM-7 字母表外的任何内容)时是 70。多段消息每段失去 7 个 GSM-7 字符或 3 个 UCS-2 字符,用于重新组装的用户数据头(User Data Header),因此长消息每段限制为 153 个 GSM-7 字符或 67 个 UCS-2 字符。一个智能引号、长破折号或表情符号会将整个消息降级为 UCS-2,并将每段限制减半。Twilio 的「Smart Encoding」自动将弯曲引号替换为直引号,以保持营销活动在更便宜的编码中。
字节限制真正咬人的地方
三种字节(而非字符)限制会让你措手不及的类别:
HTTP 请求头。没有正式规范最大值,每个服务器都强制执行一个。Apache 的 LimitRequestFieldSize 默认每个头 8 KB;Nginx 的 large_client_header_buffers 默认 4 × 8 KB;IIS 默认 16 KB;AWS Application Load Balancer 接受每头 16 KB 和总计 60 KB;Cloudflare 允许 32 KB。具有膨胀声明集的 JWT 经常超过 Apache 的 8 KB 默认值,这是基于令牌的身份验证最常见的生产故障模式。
云对象存储键。S3 和 GCS 都将对象键限制为 1024 字节 UTF-8。Azure Blob Storage 将 blob 名称限制为 1024 字符(内部 UTF-16)。对于 S3,一个 CJK 密集的文件名(每字符 3 字节)在 ~341 字符处达到上限;一个表情符号密集的文件名(每字符 4 字节)在 ~256 处,远早于开发者的预期。
数据库行和索引限制。MySQL InnoDB 在 DYNAMIC 行格式上有 65,535 字节行大小和 3072 字节索引键前缀限制(在旧的 COMPACT 上为 767)。一个 VARCHAR(255) utf8mb4 列需要 1020 字节(255 × 4)的索引空间,在 DYNAMIC 上没问题,在 COMPACT 上会坏。MongoDB BSON 文档上限 16 MB。DynamoDB 项上限 400 KB(包括属性名)。Redis 值上限 512 MB。
常见使用场景
- 数据库字段验证,在 INSERT 之前确认用户提交的名称会适合,特别是当列是
VARCHAR(255)utf8mb4 而输入是 CJK 时。 - SMS 营销文案,确认消息保持在 GSM-7(负载中每可见字符约 1 字节),而不是因为弯曲引号意外跌入 UCS-2。
- API 负载预算,确认 JSON 主体在已知限制下(DynamoDB 400 KB,AWS Lambda 负载 6 MB 同步,256 KB 异步)。
- 云对象键,确认 S3 / GCS 键在非 ASCII 转码后保持在 1024 字节以下。
- 表情符号披露,准确查看表情符号或家庭 ZWJ 序列为字符串增加多少「重量」。
- 编码选择,比较 UTF-8 vs UTF-16 字节大小;对于主要是 CJK 的内容,UTF-16 可能更紧凑(每 CJK 字符 2 字节 vs UTF-8 中的 3 字节)。
常见错误
- 信任 JavaScript 的
.length来获取字节大小。.length返回 UTF-16 编码单元,不是字节也不是字符。对于 UTF-8 字节,使用new TextEncoder().encode(text).length;对于可见字符,使用Intl.Segmenter。 - 假设 MySQL
utf8真的是 UTF-8。它是一个 3 字节子集,会悄悄丢弃表情符号。在任何接触用户提交文本的列上始终使用utf8mb4(以及utf8mb4_unicode_ci作为排序规则)。 - 假设一个表情符号等于一个字节。单个表情符号在 UTF-8 中是 4 字节,在 UTF-16 中是 4 字节(代理对)。家庭 ZWJ 序列可能超过 30 字节,但看起来像一个字符。
- 将 UTF-8 BOM 计为内容。文件开头的三字节 UTF-8 BOM
EF BB BF是元数据,不是文本。大多数 CLI 工具(awk、head、sed)将其视为第一个字段的一部分,这是许多「为什么我的第一个列名有一个奇怪的字符」错误的根源。 - 为非 ASCII 文本报告「ASCII 字节」计数。ASCII 无法表示 U+007F 以上的字符。此计数器在输入包含非 ASCII 时发出警告,以便你知道 ASCII 列没有意义。
更多常见问题
为什么一个表情符号是 4 字节,而文本字符只有 1 字节?
UTF-8 对 ASCII(U+0000 到 U+007F)使用 1 字节,对拉丁扩展 / 希腊文 / 西里尔文 / 阿拉伯文 / 希伯来文(U+0080 到 U+07FF)使用 2 字节,对大多数 CJK 和印度文字(U+0800 到 U+FFFF)使用 3 字节,对表情符号和补充平面字符(U+10000 到 U+10FFFF)使用 4 字节。像 😀(U+1F600)这样的典型表情符号在补充平面中,花费 4 字节。组合表情符号(例如家庭 👨👩👧👦)由几个基础表情符号通过零宽度连接符粘合在一起;每个基础表情符号是 4 字节,每个连接符是 3 字节,所以 4 个的家庭需要 4×4 + 3×3 = 25 字节,看起来像一个字符。
MySQL utf8 实际上是什么意思?
在 MySQL 中,字符集别名 utf8 是真正 UTF-8 的最大 3 字节子集。它可以编码 Unicode 基本多语言平面中的每个字符,但无法存储表情符号或 U+FFFF 以上的任何字符。MySQL 中真正的 4 字节 UTF-8 是 utf8mb4,自 MySQL 5.5.3(2010 年 3 月)起可用,自 MySQL 8.0(2018 年 4 月)起默认。如果你可以更改模式,始终使用 utf8mb4 和 utf8mb4_0900_ai_ci 排序规则(或较旧服务器上的 utf8mb4_unicode_ci)。
这个计数器包括 UTF-8 字节序标记吗?
不。UTF-8 字节序标记是 Windows 上的 Excel 在文件开头需要的三个字节 EF BB BF,用于检测 UTF-8。计数器测量你粘贴的文本的字节;如果你的文本碰巧以 BOM 开头,这三个字节会被算作内容。如果你想知道你的文件字节是否会达到限制,只粘贴文件的主体,而不是 BOM。
为什么我的中文文本在 UTF-8 中显示每字符 3 字节?
几乎所有 CJK 表意文字都位于 Unicode 范围 U+4E00 到 U+9FFF(CJK Unified Ideographs 块),UTF-8 将它们编码为每个 3 字节。因此 100 字符的中文句子是 300 UTF-8 字节。在 UTF-16 中,相同的文本是 200 字节(每字符 2 字节),所以对于主要是 CJK 的内容,UTF-16 更紧凑。UTF-8 在拉丁与 CJK 混合内容中获胜,因为拉丁字符每个 1 字节而不是 2 字节。
我的文本会上传到任何地方吗?
不。字节计数器完全在你的浏览器中运行。UTF-8 字节计数来自标准 TextEncoder API(每个现代浏览器都支持),UTF-16 和 Latin-1 计数来自简单循环。没有网络请求,没有服务器调用,没有日志记录。一旦页面加载,工具就离线工作。安全用于检查 API 令牌、内部数据或你不会粘贴到第三方文本计数器中的任何内容。