使用方法
- 把 8 位一组的二进制串粘进输入框。页面打开时已经预置示例:
11100110 10011111 10110011 11100110 10110011 10001001 00100000 01001111 01001011 11110000 10011111 10011000 10000000,一共 13 组、104 位。 - 分隔符随你怎么写:空格、换行、逗号、制表符都会被过滤掉,直接连写成
111001101001111110110011也一样能识别。唯一的要求是有效 0/1 字符的总数是 8 的整数倍。 - 点「开始还原」,结果框给出文本,下面的表格逐字节告诉你每个字节扮演什么角色:ASCII 单字节、2/3/4 字节首字节、还是续字节,以及掩码取值和它最终归属哪个字符。
- 碰到非法序列时默认按容错处理:整段解码不中断,非法的那一段换成替换字符
U+FFFD(显示成 �),表格里那一行会标红,位置清清楚楚。想看严格结果就勾上「严格模式」,此时遇到第一个非法序列就直接报错并指出是第几个字节。 - 输入框里按 Ctrl + Enter(macOS 用 Cmd + Enter)等同于点「开始还原」。表格默认 12 行,「加载更多」每次再放 12 行;「复制对照表」输出 TSV,「导出 CSV」输出带 BOM 的文件,Excel 打开不乱码。
这个二进制转文本工具能解决什么问题
一是读懂协议与文件头。抓包工具、串口日志、文件十六进制编辑器里,字节常常被展开成 8 位串,想确认一段 11100110 10011111 10110011 到底是哪个汉字,直接贴进来即可。
二是验证编码是否正确。某段文本显示成乱码时,把原始字节贴进来,如果表格里出现大量 U+FFFD,说明字节流本身就不是合法 UTF-8;如果全部正常解出,问题多半出在别处(字体、传输截断或渲染环节)。
三是讲清「一个汉字几个字节」。ASCII 字母 1 字节、常用汉字 3 字节、表情 4 字节,这个分档在表格里一眼能看到,比背规则牢靠。存储容量、字段长度、传输分包都按字节算,用这里的数字做估算是准确的。
四是排查「截断到半个字符」的事故。日志被按定长切片时,末尾常剩半截多字节序列。本页会把这种残尾单独标成一个替换字符,你就能确认是截断导致的乱码,而不是编码选错。
本页不做这些事:不做反向的文本到 8 位串转换(那有专门的一页);不解析 GBK、Big5、Shift_JIS 等非 UTF-8 编码;不做进制计算。要按位做与、或、异或运算请用「二进制计算器」,要看十六进制形态的字节流请用「十六进制转文本转换器」。
还原原理:RFC 3629 的 UTF-8 字节分档与掩码
二进制转文本的核心不是「把 0 和 1 变成字符」,而是先把 8 位串还原成字节,再按 UTF-8 规则把字节还原成字符。前者是纯粹的进制换算(每 8 位一字节,按权相加),后者才是难点:一个字符可能占 1 到 4 个字节,必须靠首字节的高位模式判断它后面还跟几个字节。
RFC 3629 把 UTF-8 的合法字节序列写成 ABNF 文法,分档是这样的:0xxxxxxx 是单字节,覆盖 U+0000–U+007F;110xxxxx 10xxxxxx 是 2 字节,覆盖 U+0080–U+07FF;1110xxxx 10xxxxxx 10xxxxxx 是 3 字节,覆盖 U+0800–U+FFFF;11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 是 4 字节,覆盖 U+10000–U+10FFFF。判断规则就是数首字节开头连续几个 1:0 个是单字节,2 个跟 1 个续字节,3 个跟 2 个,4 个跟 3 个。续字节一律以 10 开头,占 6 个有效位。
掩码是拼接的关键。首字节里真正有效的是低位:2 字节首字节取 & 0x1F(低 5 位),3 字节取 & 0x0F(低 4 位),4 字节取 & 0x07(低 3 位);每个续字节取 & 0x3F(低 6 位)。取出的位依次左移拼接,就得到码点。以实例里的柳为例:三个字节是 E6 9F B3,化成二进制是 11100110 10011111 10110011;首字节取低 4 位得 0110,两个续字节各取低 6 位得 011111 和 110011;拼起来是 0110 0111 1111 0011,也就是十六进制 67F3,十进制 26611,正是 U+67F3。
RFC 3629 比「数前导 1」更严。它同时禁止了三类序列,这也是「非法序列」判定的依据:一是过长编码(overlong),同一个码点用了比必要更长的字节数,例如用 C0 80 表示 U+0000、用 E0 80 80 表示 U+0000,合法写法必须是最短形式;二是代理区码点,U+D800–U+DFFF 这两个区间在 UTF-8 里永远不允许出现,它们的编码是 ED A0 80 到 ED BF BF,统统非法;三是超出 U+10FFFF,所以首字节 F5–FF 以及 F4 90 及以后的序列都不合法。规范写法把 3 字节首字节拆成三段(E0 后面必须跟 A0–BF,ED 后面必须跟 80–9F,其余跟 80–BF),4 字节同理(F0 后跟 90–BF,F4 后跟 80–8F),就是为了把这几类非法形态堵在语法层。
页面里做的是同一件事,并且和浏览器原生实现交叉验证。解析用的是手写状态机:读首字节判长度、逐个校验续字节、用掩码拼码点、再检查是否过长编码或落在代理区;非法时按 WHATWG 编码标准里 TextDecoder 的做法只消费 1 个字节再重新同步,把这一字节记作 U+FFFD。之所以只消费 1 字节而不是整组丢掉,是为了让 C0 80 这种「两个字节各自都不合法」的输入产出两个替换字符,与 new TextDecoder('utf-8').decode() 的输出逐字符一致;勾选严格模式时则改用 new TextDecoder('utf-8',{ fatal: true }) 的行为,遇到第一个非法序列直接抛错。最后用 String.fromCodePoint() 把码点装回 JavaScript 字符串——注意这一步之后,U+10000 以上的字符在内存里就变成 UTF-16 代理对了。
完整示例(数值仅作演示)
示例条件与页面默认值完全一致:输入 13 组 8 位串,共 104 位、13 字节,勾选状态为默认(容错模式)。解析结果如下:
- 字节
E6 9F B3→柳(U+67F3,3 字节,落在 U+0800–U+FFFF 档); - 字节
E6 B3 89→泉(U+6CC9,3 字节); - 字节
20→ 空格(U+0020,单字节); - 字节
4F 4B→OK(U+004F、U+004B,各 1 字节); - 字节
F0 9F 98 80→😀(U+1F600,4 字节,首字节F0取低 3 位得000,拼接后为1 1111 0110 0000 0000)。
把账算清:汉字 2 个 × 3 字节 + 空格 1 字节 + ASCII 字母 2 字节 + 表情 4 字节 = 13 字节,解出 6 个码点,在 JavaScript 字符串里占 7 个 UTF-16 码元——多的那 1 个码元来自 😀。
把这 13 个字节的角色列成表,就是页面下方那张明细表的静态版本(这里已按字符归组):
| 8 位串 | 十六进制 | 字节角色 | 掩码取值 | 归属字符 |
|---|---|---|---|---|
| 11100110 | E6 | 3 字节首字节 | 1110 & 0x0F = 0110 | 柳 |
| 10011111 | 9F | 续字节 | 10 & 0x3F = 011111 | 柳 |
| 10110011 | B3 | 续字节 | 10 & 0x3F = 110011 | 柳 |
| 11100110 | E6 | 3 字节首字节 | 1110 & 0x0F = 0110 | 泉 |
| 10110011 | B3 | 续字节 | 10 & 0x3F = 110011 | 泉 |
| 10001001 | 89 | 续字节 | 10 & 0x3F = 001001 | 泉 |
| 00100000 | 20 | ASCII 单字节 | 不取掩码 | (空格) |
| 01001111 | 4F | ASCII 单字节 | 不取掩码 | O |
| 01001011 | 4B | ASCII 单字节 | 不取掩码 | K |
| 11110000 | F0 | 4 字节首字节 | 11110 & 0x07 = 000 | 😀 |
| 10011111 | 9F | 续字节 | 10 & 0x3F = 011111 | 😀 |
| 10011000 | 98 | 续字节 | 10 & 0x3F = 011000 | 😀 |
| 10000000 | 80 | 续字节 | 10 & 0x3F = 000000 | 😀 |
柳 的三个掩码值是 0110、011111、110011,按 4 + 6 + 6 位拼成 0110011111110011,十六进制就是 67F3;😀 的四个掩码值是 000、011111、011000、000000,按 3 + 6 + 6 + 6 位拼成 000011111011000000000,十六进制 1F600。这两条加起来正好说明:首字节的前导 1 越多,可用位数越多,能表示的码点范围越大。
首字节判型与字节数对照表
下表按 RFC 3629 的合法区间逐档列出。注意「合法首字节范围」这一列——它不是简单的 c0–ff,而是被规范收紧过的,这一段正是非法序列判定的全部依据。
| 首字节形态 | 合法首字节 | 总字节数 | 码点范围 | 有效位分配 | 典型字符 |
|---|---|---|---|---|---|
| 0xxxxxxx | 00–7F | 1 | U+0000–U+007F | 7 | A 0F |
| 110xxxxx | C2–DF | 2 | U+0080–U+07FF | 5 + 6 | © U+00A9 |
| 1110xxxx | E0–EF | 3 | U+0800–U+FFFF | 4 + 6 + 6 | 中 柳 |
| 11110xxx | F0–F4 | 4 | U+10000–U+10FFFF | 3 + 6 + 6 + 6 | 😀 U+1F600 |
| 10xxxxxx | — | — | 不能作首字节 | 6(仅作续字节) | 单出现即 U+FFFD |
| 1100000x | C0–C1 | — | 非法(必然过长编码) | — | C0 80 → 两个替换字符 |
| 11111xxx | F5–FF | — | 非法(超出 U+10FFFF) | — | F5 80 80 80 → 四个替换字符 |
还有几条被规范收窄的边界,光看首字节范围看不出来,需要连着第二个字节一起判:E0 后的第一个续字节必须在 A0–BF 之间,否则就是过长编码;ED 后的第一个续字节必须在 80–9F 之间,否则会落到代理区;F0 后必须是 90–BF;F4 后必须是 80–8F。本页的状态机按这四条逐一校验,四条之外的组合一律记 U+FFFD。
输入范围、边界与精度说明
- 有效 0/1 位数必须是 8 的整数倍。少了或多了都会报错,并告诉你余数是多少——例如 12 位会提示「多出 4 位」。不允许自动补零,因为补零会凭空造出一个
00字节,可能把非法序列变成看似合法的序列。 - 位数上限 640000 位,也就是 80000 字节。超过之后页面直接报错,不静默截断:截断恰好是造成「半个字符」的最常见原因,而这个问题正是本页要帮你查的。
- 只认 0 和 1。空格、换行、制表符、逗号会被当分隔符过滤;出现其它字符(包括
2、x、全角数字)会报错并指出第一个非法字符是什么、在第几位。 - 非法序列按「只消费 1 字节」处理。这是 WHATWG 编码标准里 TextDecoder 的做法,也是本页与浏览器原生实现逐字符对齐的关键:
C0 80会出两个 �、ED A0 80会出三个 �、F4 90 80 80会出四个 �。多字节首字节后面跟错续字节时,只替换首字节,后续合法字节继续正常解——例如E6 41解出的是「�A」而不是一整段 �。 - 替换字符本身就是三字节。
U+FFFD的 UTF-8 编码是EF BF BD。所以「13 个字节里混进一处非法」时,输出文本的 UTF-8 长度会变长,而不是变短——替换只保证可读,不保证长度守恒。 - 代理区在 UTF-8 层永远非法。U+D800–U+DFFF 只存在于 UTF-16。看到
ED A0 80这类序列,它不是「UTF-8 里的代理对」,而是明确违规的字节,本页一律判成非法。 - 严格模式与容错模式的差别只在第一个非法序列。容错模式继续解析完剩余字节并给出完整表格;严格模式在第一个非法序列处抛错并指出它是第几个字节,后面的字节不再解析。要排查「整段坏在哪」用容错模式,要做数据校验用严格模式。
- 口径固定为 UTF-8。二进制转文本这一步只按 RFC 3629 的 UTF-8 解,不提供 GBK / Big5 / Latin-1 的切换入口——同一串
D6 D0在 GBK 里是「中」,在 UTF-8 下会解成两个替换字符,口径混用才是乱码的主因。遇到非 UTF-8 字节流请先用对应编码解码,再回到本页对照。
常见问题
为什么一个汉字是 3 个 8 位串,而字母只要 1 个?
因为 UTF-8 是变长编码。ASCII 范围 U+0000–U+007F 只需要 7 个有效位,塞进 1 个字节正好;常用汉字落在 U+0800–U+FFFF,需要 16 个有效位,分成 4 + 6 + 6 三段装进 3 个字节;表情这类 U+10000 以上的字符需要 21 位,分成 3 + 6 + 6 + 6 装进 4 个字节。段落数由首字节的前导 1 个数决定。示例里 柳 是 E6 9F B3 三组,O 是 4F 一组,差别就来自这里。
UTF-8 里到底有没有「代理对」?
没有。代理对是 UTF-16 的机制:U+10000 以上的字符在 UTF-16 里被拆成两个各 16 位的码元,例如 😀 是 D83D DE00。UTF-8 不这么做,它直接用 F0 9F 98 80 四个字节表示。所以 ED A0 80 这种「长得像代理」的序列不是代理对,而是违规字节——UTF-8 里 U+D800–U+DFFF 被明文禁止。
为什么非法字节会变成「�」,一个还是好几个?
� 是替换字符 U+FFFD(UTF-8 字节 EF BF BD)。数量取决于几个字节各自都无法构成合法序列:本页按「只消费 1 字节再重新同步」处理,所以 C0 80 出 2 个、ED A0 80 出 3 个、F4 90 80 80 出 4 个。这和浏览器 TextDecoder 的输出一致,可以拿它对照验证。
能用它解 GBK 编码的中文吗?
不能,而且会满屏替换字符。GBK 用 2 个字节表示一个汉字(例如「中」是 D6 D0),高位字节范围是 81–FE,在 UTF-8 看来大多是非法首字节或落不进的组合。如果手里确定是 GBK 字节流,应该先用 GBK 解码器还原成文字,再按 UTF-8 重新编码,而不是直接喂给本页。
输入里没有分隔符,一整串能不能认?
能。工具先把所有 0/1 抽出来,再按每 8 位切一刀。所以 111001101001111110110011 和带空格的写法等价。反过来,如果你的串是按「每行一个字节」粘的,换行也会被当作分隔符,结果完全一样。
为什么 C0 80 不算合法的 U+0000?
因为它是过长编码。U+0000 的正确 UTF-8 写法是单字节 00,用两个字节 C0 80 表示同一个码点是冗余的,RFC 3629 明确禁止。这条规则不是洁癖:如果允许过长编码,同一个字符会有多种字节表示,做签名校验、黑名单匹配、路径规范化时就会出现绕过漏洞,所以历史上被专门堵掉了。
表格里的「掩码取值」一列有什么用?
它是从字节到码点的中间步骤,方便你手工复核。首字节 E6 的低 4 位是 0110,两个续字节各贡献 6 位,拼起来就是码点。你可以拿这张表当教学材料:把 柳 那三行按 4 + 6 + 6 的顺序拼一遍,能得到 67F3,和码点列完全对上。填充位(首字节里那几个 x)永远是 0,不参与计算。
超过 640000 位会怎样?会帮我截断吗?
不会截断,会直接报错。截断在这里是最坏的处理方式:多字节字符被切开后,剩下的半截序列会被判成非法,于是你看到一堆 � 却不知道是自己截的。正确做法是分段处理,并且每次都让每段的有效位数保持 8 的整数倍——如果原始数据是按字符切的,字节边界天然对齐,就不会出问题。
相关工具
- 文本转ASCII转换器:只看每个字符的 ASCII 码,适合纯英文与符号的场景。
- ASCII转文本转换器:把十进制码值还原成字符,和本页的二进制入口互补。
- 十六进制转文本转换器:字节已经是
E6 9F B3形态时用它更直接,不用先展开成 8 位串。 - 文本转十六进制转换器:反过来看一段文字占哪些字节,配合本页可以自查编码是否正确。
- 二进制转十进制转换器:把 8 位串按位加权求值,处理无符号整数时比看字节更直观。
- 二进制转十六进制转换器:先把 8 位串折成十六进制,再对照本页的字节角色表。
- 二进制计算器:做与、或、异或、移位等按位运算,不涉及字符编码。
- 编码解码:查看全部编码解码工具。