使用方法
- 打开页面,输入框已预填 中文abc134,结果区直接显示 E4B8ADE69687616263313334——这是 12 字节编出的 24 个 hex 字符。改动输入内容会立刻重算,不用点按钮。
- 多行输入按 Ctrl/Cmd + Enter 触发一次完整重算。这里用组合键而不是裸 Enter,是因为输入框是多行文本,Enter 必须留给换行——而换行符本身就是待编码的数据,它的 hex 是
0a。 - 选择分隔符:无 / 空格 / 每 8 字节换行 / 每 16 字节换行。后两种是为了对齐
hex dump的常规排版。分隔符只影响显示,不改动任何一个字节,四种格式里 hex 长度(不含分隔)始终相同。 - 切换大小写、勾选 0x 前缀。它们同样只是显示约定:小写
e4b8ad与大写E4B8AD数值相同,加前缀后每字节多 2 个字符,字节数不变。页面默认输出大写,与反向解码页的默认输入形态保持一致;正文对照表按 RFC 习惯统一用小写呈现。 - 看结果区下方六个指标:字符数(按码点)、UTF-16 长度、UTF-8 字节数、hex 长度(不含分隔)、膨胀倍数、字节与字符之比。默认示例是 8 码点 / 8 个 UTF-16 码元 / 12 字节,12 与 8 的差额只有一个来源:两个汉字各占 3 字节。
文本转十六进制转换器能解决什么问题
先把口径说清楚:本页输出的是文本按 UTF-8 编码后的字节的十六进制,不是「字符的 Unicode 码点」。这两者经常被混为一谈,数值却完全不同——「中」的码点是 U+4E2D,而它的 UTF-8 字节是 E4 B8 AD。文本转十六进制转换器算的是后者。同样叫「转十六进制」,数值口径与字节口径是两件事:把十进制数 255 变成 FF 属于数值进制转换,把「中文」变成 E4B8ADE69687 属于文本编码,两者只在 ASCII 区间才碰巧一致。
一是给接口 / 协议 / 硬件准备字节。串口指令、蓝牙特征值、部分 HTTP 签名、嵌入式寄存器,要求的是一串十六进制字节而不是字符串。要在 payload 里塞一个「中文」,你就必须知道它是 E4 B8 AD、长度为 3,而不是想当然的一位汉字。本页把字节数与 hex 长度分开列,正是为了让「3 字节 → 6 个 hex 字符」这个换算随手可查。
二是核对编码到底对不对。看到乱码,第一步往往是把原文转成 hex,看字节落在哪一段区间:全在 00~7F 是 ASCII;出现 C2~DF 说明混进了 2 字节字符;E0~EF 是 3 字节(绝大多数汉字都在这一档);F0~F4 是 4 字节(emoji 与增补平面)。把「猜编码」变成「看字节」,是排查乱码最省时间的一步。
三是造测试数据与转义文本。写单测时要构造含中文、emoji、控制字符的字节串;把参数塞进 URL、Cookie、配置文件时,也常要求先拿到字节再做百分号编码或 \xNN 转义。本页给出的就是这一层最原始的字节。
四是与 JSON 的 \u 转义互校。JSON 用的是 UTF-16 码元转义,和本页的 UTF-8 字节口径并不是一套算法:「中」在两边都恰好是 6 个字符(\u4e2d 对 e4b8ad),是个巧合;但 😀 在 JSON 里是 12 个字符(\ud83d\ude00),在本页只有 8 个(f09f9880)。把两套口径搞混,是「转义后长度对不上」最常见的成因。
本页不做这几件事:不做 GBK / Big5 编码——浏览器原生 TextEncoder 只输出 UTF-8,别的编码得靠专门的字库;不做数值进制转换——那是十进制 / 二进制 / 十六进制互转;也不做反向的「十六进制转文本」,那是本页的镜像页,两页互为反方向、可交叉验证。
原理和变量:字符 → 码点 → UTF-8 字节 → hex 的四段转换
编码链路一共四段:JS 字符串(UTF-16 码元)→ Unicode 码点 → UTF-8 字节 → 每字节 2 位十六进制。new TextEncoder().encode(s) 一步走完前两段,直接返回一个 Uint8Array;剩下的转换是纯机械操作。文本转十六进制转换器的全部工作,就是保证这条链上每一环都不出错。理解这个链条的关键是记住UTF-16 和 UTF-8 是两套长度不同的编码,中间必须经过码点这一层才能对齐。
第一段:码点决定 UTF-8 字节数。RFC 3629 把码点区间与字节数一一对应,没有例外:
U+0000~U+007F→ 1 字节,位模式0xxxxxxx,hex 是 2 个字符(ASCII 区);U+0080~U+07FF→ 2 字节,110xxxxx 10xxxxxx,hex 是 4 个字符(拉丁扩展、希腊字母等);U+0800~U+FFFF→ 3 字节,1110xxxx 10xxxxxx 10xxxxxx,hex 是 6 个字符(绝大多数汉字、全角标点);U+10000~U+10FFFF→ 4 字节,11110xxx加 3 个10xxxxxx,hex 是 8 个字符(emoji、增补平面)。
第二段:单字节必须补零,这是最容易写出静默 bug 的地方。一个字节 8 位对应 2 位十六进制,所以每个字节都必须输出满 2 个字符。0x05 写成 "5" 就错了。实测反例:字节 [0x05, 0x5A, 0xFF] 正确结果是 055aff(6 个字符),若省略补零会得到 55aff(5 个字符)——长度不再是「字节数 × 2」的偶数,反向解析时必然错位、整串作废。页面统一用 t.length < 2 ? '0' + t : t 强制补足两位。
第三段:JS 字符串按 UTF-16 码元存放,U+10000 以上必须用代理对。所以一个 emoji 的 s.length 是 2 而不是 1,而 [...s].length(按码点迭代)才是 1。落单的代理项——只有高代理 \uD83D 或只有低代理 \uDE00——不是一个合法字符:UTF-8 规范禁止编码 U+D800~U+DFFF 这段保留区,TextEncoder 会把它静默替换成 U+FFFD 的字节 EF BF BD(3 字节)。替换之后再解码回文本就是一个 �,原文信息永久丢失。本页因此直接拒绝含落单代理项的输入,而不是让你对着 � 猜原文。
第四段:分隔符、大小写、0x 前缀都是显示约定,不进入字节流。它们只在最后一步拼接字符串时生效。可以量化的关系是:hex 字符数(无分隔、无前缀)= 字节数 × 2;改用空格分隔时再加 字节数 − 1 个空格;每字节加 0x 前缀则每字节多 2 个字符。默认示例 12 字节,于是无分隔是 24 字符、空格分隔是 24 + 11 = 35 字符、加前缀是 48 字符——三者的字节序列完全一样。文本转十六进制转换器把这四种格式都做成了可切换项,但底层只算一次字节。
完整示例(数值仅作演示)
示例条件与页面打开时的默认值完全一致:文本 = 中文abc134,输出 = E4B8ADE69687616263313334。结果区在打开时就显示着这串 hex,点一次「转十六进制」得到完全一样的结果。文本转十六进制转换器的默认值之所以固定成这一组,是为了能直接粘进反向页做交叉验证。
- 字符数(按码点)8:「中」「文」各 1 个码点,
abc134六个 ASCII 字符; - UTF-16 长度 8:没有增补平面字符,码元数等于码点数;
- UTF-8 字节数 12 = 3(中)+ 3(文)+ 1 + 1 + 1 + 1 + 1 + 1;
- 无分隔 hex 长度 24 = 2 × 12;空格分隔是 35 = 24 + (12 − 1);加 0x 前缀是 48;
- 逐字节拆开:
0xe4 0xb8 0xad(中)0xe6 0x96 0x87(文)0x61 0x62 0x63(abc)0x31 0x33 0x34(134); - 差额校验:字节 12 − 码点 8 = 4 = 2 × (3 − 1),正好是两个 3 字节汉字每个多出的 2 字节;
- 膨胀倍数:24 ÷ 8 = 3 倍(纯 ASCII 输入只有 2 倍,纯 emoji 输入可到 8 倍);
- 交叉验证:把
E4B8ADE69687616263313334粘进「十六进制转文本转换器」,解出来正好是「中文abc134」,两页互为反方向、逐位吻合。
输入范围与对照表
输入侧的规则都对应一种真实的输入形态,而不是凭空约定:
| 输入形态 | 示例 | 页面行为 | 为什么要这么定 |
|---|---|---|---|
| 纯 ASCII | A1~` | 正常编码,1 字符 1 字节 | 最常见场景,hex 长度正好是字符数 × 2 |
| 汉字 / 全角标点 | 中文, | 正常编码,1 字符 3 字节 | U+0800~U+FFFF 统一 3 字节,hex 长度 6 |
| emoji / 增补平面 | 😀🀄𝄞 | 正常编码,1 码点 4 字节 | U+10000 以上既要代理对又要 4 字节 UTF-8 |
| 控制字符 | 换行 / TAB | 正常编码,hex 为 0a / 09 | 控制字符也是数据,必须编进字节而不是丢掉 |
| 空输入 | (留空) | 拒绝 | 空串的 hex 结果同样是空串,无法与「没填」区分 |
| 落单代理项 | 截断的 😀 | 拒绝 | UTF-8 禁止编码 U+D800~U+DFFF,库会静默换成 EF BF BD |
| 超长输入 | > 200 万码元 | 拒绝(20 万起先提示) | 逐字节循环加超长 DOM 文本都会把页面卡死 |
下表是 20 组字符的逐项实测:「UTF-8 字节数」与「hex 字符数」两列始终满足「hex = 字节 × 2」。前 12 行默认显示,点「加载更多行」展开后 8 行;点「导出 CSV」可整表带走(带 BOM,Excel 打开中文不乱码)。表中 hex 统一用小写 0-9a-f 呈现,与页面输出的默认大写只是写法差异,数值完全一致。
| 行 | 字符 | 类别 | 码点 | UTF-8 字节数 | hex | hex 字符数 |
|---|---|---|---|---|---|---|
| 1(默认) | A | ASCII 大写字母 | U+0041 | 1 | 41 | 2 |
| 2 | a | ASCII 小写字母 | U+0061 | 1 | 61 | 2 |
| 3 | 1 | ASCII 数字 | U+0031 | 1 | 31 | 2 |
| 4 | ~ | ASCII 标点 | U+007E | 1 | 7e | 2 |
| 5 | é | 拉丁扩展 2 字节 | U+00E9 | 2 | c3a9 | 4 |
| 6 | Ω | 希腊字母 2 字节 | U+03A9 | 2 | cea9 | 4 |
| 7 | 中 | CJK 汉字 3 字节 | U+4E2D | 3 | e4b8ad | 6 |
| 8 | , | 全角标点 3 字节 | U+FF0C | 3 | efbc8c | 6 |
| 9 | € | 欧元符号 3 字节 | U+20AC | 3 | e282ac | 6 |
| 10 | 😀 | emoji 增补平面 4 字节 | U+1F600 | 4 | f09f9880 | 8 |
| 11 | 𝄞 | 音乐符号 4 字节 | U+1D11E | 4 | f09d849e | 8 |
| 12 | 换行 \n | LF 控制符 1 字节 | U+000A | 1 | 0a | 2 |
| 13 | 你 | CJK 汉字 3 字节 | U+4F60 | 3 | e4bda0 | 6 |
| 14 | 文 | CJK 汉字 3 字节 | U+6587 | 3 | e69687 | 6 |
| 15 | © | 版权符号 2 字节 | U+00A9 | 2 | c2a9 | 4 |
| 16 | ß | 德语 eszett 2 字节 | U+00DF | 2 | c39f | 4 |
| 17 | ¥ | 全角货币符号 3 字节 | U+FFE5 | 3 | efbfa5 | 6 |
| 18 | 制表 \t | TAB 控制符 1 字节 | U+0009 | 1 | 09 | 2 |
| 19 | DEL \x7f | 删除符 1 字节 | U+007F | 1 | 7f | 2 |
| 20 | 🀄 | 麻将红中 4 字节 | U+1F004 | 4 | f09f8084 | 8 |
第 5 行值得注意:é 的码点 U+00E9 已经越过 U+007F,于是从 1 字节跳到 2 字节,hex 从 2 个字符变成 4 个。第 10、11、20 行则是 U+10000 以上的样本,UTF-16 里各自占 2 个码元、UTF-8 里占 4 字节——「1 个字符却要 8 个 hex 字符」的膨胀上限就出现在这一档。第 12、18、19 行提醒一件事:控制字符不是「看不见就可以不管」,它们同样要编成字节,DEL(U+007F)甚至刚好卡在 ASCII 区的最右端。
边界与精度
- 补零是硬要求,不是美化。只要有一个字节的值小于
0x10,它的十六进制就只有 1 位,不补零整串长度立刻不再是偶数。实测[0x05, 0x5A, 0xFF]补零后是055aff,不补零是55aff——后者反解时会被判为奇数长度而失败。字节里出现00~0f的概率不低,所以这一步必须有。 - 落单代理项会被静默替换,所以本页改为直接拒绝。
TextEncoder遇到\uD83D或\uDE00不会报错,而是输出EF BF BD(U+FFFD 的 UTF-8 字节)。这意味着从 hex 反解看到EFBFBD时,你无法区分原文里原本就有一个 U+FFFD,还是有一个被截断的 emoji。替换不可逆,页面因此把这类输入挡在编码之前,并明确告诉你有几个落单代理项。 - 膨胀率取决于字符构成,范围是 2 倍到 8 倍。hex 长度(无分隔、无前缀)恒等于字节数 × 2,所以膨胀率 = 字节数 ÷ 码点数 × 2。纯 ASCII 是 1:1,膨胀 2 倍;纯中文是 3:1,膨胀 6 倍;纯 emoji 是 4:1,膨胀 8 倍。实测 100 个 ASCII 输出 200 个 hex 字符,100 个汉字输出 600 个,100 个 emoji 输出 800 个——按这个比例可以提前预估结果区会有多长。
- 长度上限分两道:20 万码元提示、200 万码元拒绝。实测 100 万个汉字编码耗时约 4 毫秒,但把它逐字节拼接成 hex 要 580 毫秒左右,再写进 DOM 就是几 MB 的文本,浏览器会明显卡顿甚至无响应。真正的瓶颈不是编码本身,而是字符串拼接与 DOM 渲染。页面在 20 万字符起给出提示、200 万字符起拒绝,并在文案里写明对应的字节数,而不是含糊地说「太长」。
- 编码方向保留 BOM,解码方向默认丢弃,这是不对称的。如果文本里真的含
U+FEFF(ZERO WIDTH NO-BREAK SPACE),本页会老老实实把它编成EF BB BF三个字节;而「十六进制转文本转换器」的TextDecoder默认会把开头的EFBBBF吃掉。所以把本页结果丢进解码工具时,如果开头是EFBBBF,长度会少 3 字节——这不是编码错误,是解码侧的默认行为。 - hex 本身不携带「这是 UTF-8」的信息。
E4B8AD只有在按 UTF-8 解释时才是「中」;换 GBK 或 Latin-1 解出来的完全是别的东西。本页固定用 UTF-8 输出,并在正文与对照表里反复标注字节数,就是为了让「这套 hex 是按什么编码产生的」永远有据可查。 - 浏览器里的换行符统一是 LF。在
textarea里按一次回车,取到的值是LF(0a),不是 Windows 的CRLF(0d0a)。所以即使你从记事本复制多行文本进来,本页输出的行尾字节也只是0a;要匹配目标平台的换行字节,必须显式在文本里补上CR,或者直接手写0d0a。这是「本地算出来字节数和对方差 1」的常见原因。
常见问题
「中」转出来是 6 个字符,可它明明只是一个汉字?
因为 hex 是字节的十六进制写法,不是字符的写法。一个 UTF-8 汉字占 3 字节,每字节 2 位十六进制,所以「中」是 E4 B8 AD——6 个字符。对照表第 7 行就是这一条:码点 U+4E2D 落在 U+0800~U+FFFF 区间,输出恰好 3 字节、6 个 hex 字符。
反过来理解更直观:字符数不是你该看的东西,字节数才是。页面的指标区把「字符数(按码点)」和「UTF-8 字节数」并排放在一起,默认示例就是 8 对 12。如果你要数的是「几字节」,看字节数那一格;如果要的是「几个字」,看字符数那一格。把「8 个汉字变成 48 个字符」当成转错了,是这类工具最高频的误判。
换个分隔符,结果看起来完全不一样,是我切换错了?
不是。分隔符只改排版,不碰字节。同一串 12 字节在四种格式下的「hex 长度(不含分隔)」都是 24,区别只在中间插了什么:无分隔是 e4b8ade69687…;空格分隔每字节之间加一个空格,总共加 11 个;每 8 字节换行则是把 12 个字节分成 2 行。验证办法很简单:把任意一种格式粘回去、去掉所有空格与换行,得到的字符串应当与「无分隔」一模一样。页面里空格分隔的长度 35 = 24 + (12 − 1),这个式子就是在说明「多出来的字符全是分隔符」。
顺带说一句选择建议:给程序解析用「无」或「空格」;要和 xxd、Wireshark 那种 16 字节一行的 dump 对照用「每 16 字节换行」;要嵌进源码常量用带 0x 前缀的版本。
emoji 明明是 1 个字符,为什么转出来 8 个 hex 字符?
因为 emoji 的码点在 U+10000 以上,属于「增补平面」,UTF-8 必须用 4 字节编码它,于是 hex 是 8 个字符(F0 9F 98 80),这是本页的膨胀上限。同时别忘了第二套长度:JS 字符串按 UTF-16 存放,同一个 emoji 要用代理对拆成 2 个码元,所以 '😀'.length 是 2,而 [...'😀'].length(按码点)才是 1。
于是同一个字符在三个地方有四个数字:码点 1 个、UTF-16 码元 2 个、UTF-8 字节 4 个、hex 字符 8 个。页面的指标区把这几个数分别列出,就是为了让你不再把它们混着用。
更极端的例子是组合 emoji:👨👩👧 由 3 个人物加 2 个 U+200D 零宽连接符组成,实测 5 个码点、8 个 UTF-16 码元、18 个 UTF-8 字节,hex 长达 36 个字符——它在视觉上是「一个」表情,在字节层面却是一个 18 字节的序列,这正是「字符」这个词在编码语境下必须被拆开的原因。
从记事本复制多行文本,行尾字节怎么只有 0a?
因为本页在浏览器里读的是 textarea 的值,而 HTML 规范要求浏览器把换行统一规范化为 LF。所以无论你从 Windows 记事本(原本是 CRLF)、macOS、还是 Linux 复制进来,取到的都只是 0a。页面的对照表第 12 行把这个值明明白白写成了 0a。
如果你要生成的字节流必须匹配目标平台,就得自己补:Windows 的 CRLF 是 0d0a,要在行尾再手工加一个 CR;老式 Mac 的 CR 是 0d。另一个坑是隐藏字符:从网页复制的文本常夹带零宽空格 U+200B(3 字节 e2808b)或不换行空格 U+00A0(2 字节 c2a0),它们肉眼看不见却会实打实出现在 hex 里。看到长度比自己数的多出几字节,优先怀疑这类字符。
默认输出是大写,结果要小写怎么办?
直接切「大小写」为小写 a-f 即可,字节序列不变。大小写只是显示约定:E4B8AD 与 e4b8ad 是同一串字节的两种写法,十六进制本身大小写不敏感。页面默认大写,是为了和反向解码页的默认输入形态对齐、方便两页互相粘贴验证;RFC 风格建议统一用小写 0-9a-f,正文里的字符对照表就按小写给出。
需要提醒的是:大小写只在「显示」层面无所谓,在「比较」层面必须统一。如果你要把本页结果和另一段小写 hex 做字符串比对,先各自归一化大小写,否则 E4B8AD 与 e4b8ad 会判为不相等——这是「明明一样却比对失败」的常见原因。页面的「复制结果」复制的是当前显示形态,所以你选了哪种大小写,粘出去就是哪种。
为什么单个字节一定要补零?不补会怎样?
因为一个字节 = 8 位 = 2 位十六进制,每个字节必须占满 2 个字符,否则整串的长度关系就断了。实测反例:字节 [0x05, 0x5A, 0xFF] 正确输出是 055aff(6 个字符),如果不补零,首字节 0x05 会变成 "5",结果成了 55aff——只有 5 个字符。
后果不是「难看」而是「解析错位」:反解程序按每 2 个字符切一刀,55aff 会把 55、af 当成两个字节,剩下的 f 落单,轻则整个解析失败,重则悄悄解出一串错误字节。凡是出现值小于 0x10 的字节(也就是 hex 只有 1 位),都必须补零。本页统一用 t.length < 2 ? '0' + t : t 处理,所以像「中」的第 7 行、换行的第 12 行都不会出问题。
我输入里有一个被截断的 emoji,为什么不让转?
因为落单代理项无法被编码成合法 UTF-8。emoji 在 JS 字符串里是一对代理码元(高代理 U+D83D + 低代理 U+DE00 这类),如果你只拿到其中一半——比如复制时被截断、或者后端按字符截取时切在了中间——剩下的那半个就是U+D800~U+DFFF 保留区里的孤立值。UTF-8 规范明确禁止编码代理项,TextEncoder 的处理方式是不报错、悄悄替换成 U+FFFD,输出 EF BF BD 三个字节。
这很危险:替换后的字节看起来「合法」,你完全不知道原文被破坏了;而且再解码回来只剩一个 �,原文是什么已经永久丢失,任何工具都还原不了。所以本页选择直接拒绝,并在提示里告诉你有几个落单代理项、它们会被替换成什么。要恢复就先找到源头把字符补全,或者干脆删掉这半个码元——不要指望编码器替你猜。
我用 JSON.stringify 得到的是 \u4e2d,和这里的 e4b8ad 不一样,该用哪个?
两套口径,用途不同,不存在「哪个对」。JSON 的 \uXXXX 转义按 UTF-16 码元来:BMP 内的字符一个转义(「中」→ \u4e2d,6 个字符),增补平面的字符要拆成两个转义(😀 → \ud83d\ude00,12 个字符)。本页的 hex 按 UTF-8 字节来:每个字节 2 位,汉字 6 个字符、emoji 8 个字符。
实测对照很能说明问题:中 两边都恰好 6 个字符,是个巧合;😀 在 JSON 里 12 个、在本页 8 个;👨👩👧 在 JSON 里 48 个、在本页 36 个。而且两者不能互相解析——把 f09f9880 当成 \u 转义去读会失败,因为它不是 4 位的 \u 序列。
怎么选:要写进 .json 文件、嵌进 JS / Java 字符串字面量,用 JSON 那种转义(这也正是「Unicode转义反转义工具」处理的东西);要让字节真正进入协议、文件、硬件的字节流,用本页的 UTF-8 hex。两者可在「十六进制转文本转换器」与「Unicode转义反转义工具」之间往返核对。
相关工具
- 十六进制转文本转换器——同一链路的反方向,把 hex 字节按 UTF-8 解回文本;与本页互为逆运算,可以拿默认值来回验证。
- 十进制转十六进制转换器——纯数值口径:把 255 变成
FF,不涉及字符编码,适合调试协议里的数值字段。 - 十六进制转十进制转换器——本页字节的数值侧对照:逐字节看十进制值,更容易发现某个字节明显超出 ASCII 范围。
- 二进制转十六进制转换器——数值口径的另一种入口,先把 0/1 串并成字节再看 hex,适合对照位模式。
- ASCII转文本转换器——纯 7 位口径,每个字节直接对应一个字符,正好能和本页的 UTF-8 结果逐行对照,看出多字节编码多占了哪几个字节。
- Unicode转义反转义工具——处理
\u4e2d这种 UTF-16 码元转义,与 hex 是同一批字符的两种文本外衣,常在源码里混着出现。 - 数字进制转换器——一次处理二 / 八 / 十 / 十六进制的批量互转,适合先把 hex 串拆成字节值再逐个核对。