文本转二进制

先按 UTF-8 把文字编成字节,再把每个字节写成定长 8 位二进制串:ASCII 占 1 字节、常用汉字占 3 字节、表情占 4 字节,逐字节给出偏移、十六进制与来源字符。

字符数(码点)5
UTF-16 码元6
UTF-8 字节数12
二进制位数96
占 4 字节的字符1
11100100 10111101 10100000 11100101 10100101 10111101 00100000 01000001
11110000 10011111 10011000 10000000
偏移十六进制二进制来源字符该字符第几个字节
0E411100100你第 1/3 字节
1BD10111101你第 2/3 字节
2A010100000你第 3/3 字节
3E511100101好第 1/3 字节
4A510100101好第 2/3 字节
5BD10111101好第 3/3 字节
62000100000(空格)第 1/1 字节
74101000001A第 1/1 字节
8F011110000😀第 1/4 字节
99F10011111😀第 2/4 字节
109810011000😀第 3/4 字节
118010000000😀第 4/4 字节

输入框里按 Ctrl + Enter(macOS 用 Cmd + Enter)立即重算,Enter 留给换行;普通输入也会在停顿后自动重算。示例里的 😀 是补充平面字符,它在 UTF-8 里占 4 字节、在 UTF-16 里占 2 个码元。

使用方法

  1. 在输入框里写或粘贴文字,上限 8000 字符。页面默认已填好一段 5 个字符的示例,打开就能看到转换结果,不用先点按钮。
  2. 选「输出格式」。默认的空格分隔最适合人工核对,也最容易按 8 位切回来;「连续 8 位串」体积最小,适合塞进紧凑的字段;「0b 前缀逗号分隔」方便直接粘进 C、Java 这类语言的数组字面量;「每字节一行」适合逐行比对十六进制清单。
  3. 填「每行字节数」,允许 1 到 64。默认 8,因为 8 个字节正好是 64 位,一行二进制读起来和处理器里一个 64 位字对齐。
  4. 点「转换为二进制」执行,或者在输入框里按 Ctrl + Enter(macOS 为 Cmd + Enter)。这个页面刻意不用裸 Enter 触发,因为 Enter 必须留给换行——文本里有没有换行会直接改变字节结果。
  5. 对照下面的字节表核对:偏移从 0 开始,一条记录就是一个字节,同时给出十六进制、二进制和它来自哪个字符。表默认显示 12 行,超出后点「加载更多」每次追加 24 行。
  6. 要带走数据,用「复制二进制结果」「复制字节表」(制表符分隔,可直接粘进表格)或「导出字节 CSV」(带 BOM,Excel 打开中文不乱码)。

这个文本转二进制工具能解决什么问题

一是看清一个字符到底占几个字节。数据库字段长度、网络报文长度、Redis 的 value 体积都以字节计,而人脑习惯按字符估算。把「你好」丢进这个文本转二进制工具,看到 6 个字节、48 位,就不会再按 2 个字符去申请 2 个字节的字段。

二是定位乱码的字节来源。一段文本存进数据库再取出来变成问号或方块,根因通常不是「编码声明写错了」,而是某一步按单字节截断了多字节字符。逐字节表会显示每个字节属于哪个字符的第几个字节——如果一个汉字只出现了「第 1/3 字节」,说明它在传输中被截断了。

三是给协议与硬件做字面量。串口指令、蓝牙特征值、嵌入式固件里的固定报文常常要写成一串二进制或十六进制常量。先在这里把文本转成二进制,再对照字节表抄成 0b 或 0x 数组,比手工算 UTF-8 可靠得多。

四是验证自己对 UTF-8 的理解。为什么 E4 BD A0 就是「你」?为什么续字节都以 10 开头?页面的表里每一行都能单独解释,适合当作编码课的对照材料。

本页不做这些事:不做任意进制互转(十进制、十六进制与二进制的数值互换请用「十进制转二进制转换器」),不做 Base64 或压缩,不做加密,也不做 GBK、Big5 这类多字节编码的转换——本页只有一种口径:UTF-8。

转换原理:UTF-8 分档与定长 8 位

第一步是编码。工具调用浏览器内置的 new TextEncoder().encode(text)。按 WHATWG Encoding Standard 的规定,TextEncoder 只有一种输出编码,就是 UTF-8;它返回一个 Uint8Array,每个元素都是 0 到 255 之间的整数。这里不用任何 ASCII 或 Latin-1 的兜底分支,因为那正是乱码的来源。

第二步是按码点遍历,而不是按 UTF-16 码元。JavaScript 的字符串以 UTF-16 存储,直接按下标循环会把一个表情读成两个「半个字符」。工具用 codePointAt(i) 取出码点,遇到大于 U+FFFF 的码点就把下标多前进一位,再用 String.fromCodePoint() 还原成完整字符,然后单独对它做一次 UTF-8 编码。这样每个字节都能准确地归属到一个字符。

第三步是定长补零。把字节写成二进制用 b.toString(2).padStart(8,'0')。padStart(8,'0') 不是装饰性的:字符 A 的字节是 0x41,二进制是 1000001,只有 7 位;如果不补零,拼出来的串长度不固定,接收端就无法按每 8 位切分还原。补齐后它是 01000001,一个字节永远对应 8 个字符。

UTF-8 的分档规则决定了每个字符占几个字节,规则按码点范围分四档:U+0000 到 U+007F 用 1 字节,首字节形如 0xxxxxxx;U+0080 到 U+07FF 用 2 字节,首字节形如 110xxxxx,后面跟 1 个 10xxxxxx;U+0800 到 U+FFFF 用 3 字节,首字节形如 1110xxxx,后面跟 2 个续字节;U+10000 到 U+10FFFF 用 4 字节,首字节形如 11110xxx,后面跟 3 个续字节。续字节一律以 10 开头,这也是为什么页面的字节表里汉字的后两个字节总是 10 打头。

汉字为什么稳定是 3 字节。CJK 统一表意文字基本区是 U+4E00 到 U+9FFF,共 20992 个码位,整段都落在 U+0800 到 U+FFFF 这一档里,所以常用汉字一律 3 字节、24 位。很多人以为一个汉字固定 2 字节,那是 GBK 的老口径:GBK 里一个汉字确实占 2 字节,但 GBK 与 UTF-8 是两套互不兼容的编码,页面的表在 UTF-8 下永远是 3 字节。

表情为什么是 4 字节。以 U+1F600 为例,它在 UTF-16 里是一对代理码元 D83D DE00,占 2 个码元、1 个码点;UTF-8 编码后的四个字节是 F0 9F 98 80。所以同一个字符,按码点数、按码元数、按字节数会得到 1、2、4 三个不同的值,这三个数在页面顶部的统计卡里分别列出。

完整示例(数值仅作演示)

示例文本就是页面输入框里的 你好 A😀:3 个汉字?不是——它由「你」「好」、一个半角空格、字母 A 和表情 😀 组成,共 5 个码点。因为表情占 2 个 UTF-16 码元,所以按码元数出来是 6;按 UTF-8 编码后是 12 个字节,也就是 96 位。逐字符的账目如下:

加起来 3 + 3 + 1 + 1 + 4 = 12 字节,与统计卡一致。按默认的「空格分隔、每行 8 字节」输出,结果正好两行:第一行 8 个字节共 71 个字符,第二行 4 个字节共 35 个字符,合计 107 个字符——比原来的 5 个字符长了约 21 倍。这就是二进制表示的真实代价:每个字节被展开成 8 个可见字符,再加分隔符。

注意第 2 个字节和第 6 个字节都是 BD,但它们的归属不同:一个是「你」的第 2 字节,一个是「好」的第 3 字节。只看字节值无法反推字符,必须结合偏移和 UTF-8 的分档规则。这正是页面把「来源字符」和「第几个字节」两列同时列出来的原因。

输入范围与字符-字节对照表

第一张表是输出体积:字节数一定时,输出字符数只由分隔符和每行字节数决定,与内容无关。表里的数按「空格分隔」计算,公式是「字节数 × 8 + (字节数 − 1)个空格」。

输入UTF-8 字节数二进制位数输出字符数(空格分隔)
1 个 ASCII 字符188
示例「你好 A😀」1296107
「你好」两个字64853
100 个 ASCII 字符100800899
1000 个 ASCII 字符100080008999

第二张表是常见字符的实测字节。同一张表里可以看到 1、2、3、4 四个分档同时出现,其中 〇 虽然读作「零」,但它属于中日韩符号区,UTF-8 下仍是 3 字节:

字符码位UTF-8 字节十六进制UTF-16 码元
AU+00411411
0U+00301301
(空格)U+00201201
éU+00E92C3 A91
ßU+00DF2C3 9F1
øU+00F82C3 B81
中U+4E2D3E4 B8 AD1
你U+4F603E4 BD A01
〇U+30073E3 80 871
€U+20AC3E2 82 AC1
😀U+1F6004F0 9F 98 802
𠮷U+20BB74F0 A0 AE B72
𝐀U+1D4004F0 9D 90 802

第三张表是分档的边界码位。判断一个字占几字节,只要看它落在哪一档,不需要查表:

码点范围字节数首字节形状边界实测
U+0000 – U+007F10xxxxxxxU+007F 编成 1 字节
U+0080 – U+07FF2110xxxxxU+0080 编成 2 字节,U+07FF 也是 2 字节
U+0800 – U+FFFF31110xxxxU+0800 编成 3 字节,U+FFFF 也是 3 字节
U+10000 – U+10FFFF411110xxxU+10000 编成 4 字节,U+10FFFF 也是 4 字节

结果边界、输入上限与舍入说明

常见问题

为什么「你好」两个字变成了 6 个字节?

因为 UTF-8 里一个常用汉字占 3 字节。「你」是 U+4F60,编码成 E4 BD A0;「好」是 U+597D,编码成 E5 A5 BD。两个字符加起来 6 字节、48 位。如果你的场景里一个汉字只占 2 字节,那用的是 GBK 而不是 UTF-8,本页不输出 GBK 结果。

一个汉字到底占几个字节?和 GBK 是什么关系?

取决于编码。UTF-8 下常用汉字是 3 字节(整个 CJK 基本区 U+4E00–U+9FFF 都在 U+0800–U+FFFF 这一档),GBK 下是 2 字节。两者互不兼容:同一串字节用 UTF-8 解会乱码,用 GBK 解也会乱码。现代网页、JSON、数据库大多默认 UTF-8,遇到老系统导出的文件才需要怀疑 GBK。

表情符号为什么占 4 个字节?

因为表情的码点通常在 U+1F600 这类补充平面里,超出了 UTF-16 单个码元能表示的范围。😀 在 UTF-16 里被拆成 D83D 和 DE00 两个码元,在 UTF-8 里被编成 F0 9F 98 80 四个字节。所以页面上「字符数」是 1、「UTF-16 码元」是 2、「字节数」是 4,三个数字都对,只是口径不同。

为什么每个字节一定要写成 8 位、前面补 0?

因为二进制串要能被切回来。A 的字节 0x41 直接转二进制是 1000001,只有 7 位;如果某些字节 7 位、某些 8 位,接收端就没法按固定长度切分,也无法判断 1000001 是 0x41 还是别的东西。补成 01000001 后,每 8 个字符必定是一个字节,这个约定必须由编码方保证。

输入里冒出 EF BF BD 是什么意思?

那是 Unicode 替换字符(U+FFFD,“�”)的 UTF-8 字节。出现它只有两种原因:原始文本里就含有孤立的代理码元(半个表情),或者上游某一步已经把无法解码的字节替换成了它。页面只是照实编码,不会去猜原本的内容——替换一旦发生就是不可逆的,只能回到源头重新取一次原始字节。

输出这么长,会不会复制不全?

输出区是有滚动条的容器,点击复制拿到的始终是完整字符串,与当前滚动位置无关。真正会截断你的是粘贴目标:聊天软件、Excel 单元格和部分输入框都有长度限制。需要搬运时优先用「导出字节 CSV」,一行一个字节,比整段二进制串更好处理。

空文本和只有空白的文本会输出什么?

空文本会报错并提示你输入内容,不会输出一个空结果让你以为转换成功了。只有空白的文本属于正常输入:空格是 0x20、制表符是 0x09、换行是 0x0A,它们会被逐字节转成二进制,只是很多人以为「看不见的字符不算内容」。

这和「十进制转二进制」是同一件事吗?

不是。本页做的编码:把字符按 UTF-8 映射成字节,再把字节展开成 8 位串,字符 → 字节 → 位串,中间一步是编码。进制互转做的是数值:把 2026 这个数从十进制写成二进制 11111101010,不涉及字符编码。所以「文本转二进制」用于看编码字节,「十进制转二进制」用于做数值换算,两者输入相同也可能是完全不同的结果。

相关工具