使用方法
- 「输入」文本框在服务端直出了示例
柳泉 A,打开页面即有一组现成数据;可以整段替换成自己的文字,中文、英文、emoji 都能放进去。 - 「方向」选转义或反转义。转义把普通文字变成可打印的编码写法;反转义把编码写法还原成文字。
- 「写法」在转义方向下三选一:反斜杠 u 加四位十六进制、反斜杠 u 加大括号写码点、反斜杠 x 加两位十六进制。选反斜杠 x 时,凡是超出 U+00FF 的字符都会自动降级成反斜杠 u 写法,页面对此单独说明。
- 在文本框里按 Ctrl 加回车触发生成;单独按回车只换行,方便一次录入多行文本。
- 结果区上方六个卡片给出码元数、码点数、UTF-8 字节数、方向、输入与输出长度;下方蓝色提示说明本次是否发生了降级或走的是哪一种写法。
- 「复制输出」取走结果全文,「复制对照表」取走下方常见字符编码表(制表符分隔),「导出 CSV」下载带 UTF-8 BOM 的文件,可直接用表格软件打开。
这个Unicode转义反转义工具能解决什么问题
程序里到处需要把「看不见的字符」写成「看得见的几个字母」。这段代码里的中文在源码里显示成乱码、日志里要核对某个字符到底是哪一个、配置文件不允许直接写中文、或者接口返回的一串编码要还原成原文,都要在文字与 Unicode 转义写法之间来回换。本页把这些换算集中到一处,转义与反转义共用同一个输入框,方向一切就换。
它同时也是一张对照表生成器。同一个汉字可以有四位写法、码点写法、反斜杠 x 写法等多种表示,页面的常见字符表把它们并排列出,省去逐个数十六进制。凡遇到「这串编码到底是不是我想要的字符」,先转一遍再对照即可。
计算原理与变量说明
三件事要先分清:码元、码点与字节不是一回事。JavaScript 字符串按 UTF-16 存放,长度属性数的是码元;一个码点可能占一个码元(BMP 内)也可能占两个(增补平面);而 UTF-8 字节数又是另一套数法,一个汉字 3 字节、一个 emoji 4 字节。示例 柳泉 A 的四位写法是 \u67f3\u6cc9\u0020\u0041,它正好四个码元、四个码点、八个 UTF-8 字节——因为四个字符都落在 BMP 内、都不需要代理项。
- 四位写法(反斜杠 u 加四位十六进制):只表示 BMP,也就是 U+0000 到 U+FFFF。每一位固定四位,不足前面补零,例如空格是 0020、字母 A 是 0041、汉字柳是 67f3。
- 码点写法(反斜杠 u 加大括号):花括号里放 1 到 6 位十六进制,直接写码点,不做零填充。示例得到
\u{67f3}\u{6cc9}\u{20}\u{41},可以看到 20 与 41 没有补零。 - 两位写法(反斜杠 x 加两位十六进制):只覆盖 U+0000 到 U+00FF。示例里空格与字母 A 写成
\x20\x41,而柳与泉因超出范围被降级,整串变成\u67f3\u6cc9\x20\x41。 - 反转义:从头扫描,遇到反斜杠先看后一个字符是 u 还是 x。是 u 且紧跟大括号就按码点读最多 6 位十六进制,否则按四位读;是 x 就读两位。读不够位数、读到非法字符或出现孤立代理项时立刻停下并说明原因,不会静默跳过。
为什么四位写法装不下 emoji。四位写法只有 16 位空间,最多表示 U+FFFF,而 emoji 这类增补平面字符的码点都大于 U+FFFF,例如笑脸 U+1F600。UTF-16 用一对 16 位的代理项来表示它们:高于 0xFFFF 的码点先减去 0x10000,高 10 位加上 0xD800 得高位代理项,低 10 位加上 0xDC00 得低位代理项。于是这个笑脸在四位写法下变成一对 \ud83d\ude00,在码点写法下则是一段 \u{1f600}。要正确还原,浏览器里的字符串长度属性算的是两个码元,需要按码点遍历才不会把一个 emoji 拆成两半。
花括号写法是 ES6 才有。反斜杠 u 加大括号的写法在 ECMAScript 2015 之后才被正式支持,在更早的环境或某些构建工具链里会被当成普通字符或直接报错。它比四位写法更直观的地方在于:码点想写多少位就写多少位,还能直接表示增补平面字符,不必手工换算代理项。
反斜杠 x 为什么会降级。两位写法为了压短长度只留了两个十六进制位,能覆盖的最大码点就是 U+00FF,也就是 Latin-1 的范围。汉字的最低码点也远高于它,所以遇到中文必然无法表示。页面没有选择静默丢弃或乱码,而是按「能短则短、不能短就退回四位」的规则处理:范围内的字符用两位,超出范围的一律改用四位写法,并在提示里告诉你有多少个字符发生了降级。这也是为什么示例里同一个空格与字母 A 用的是两位、柳与泉用的是四位。
孤立代理项是什么。代理项区间 U+D800 到 U+DFFF 在 UTF-16 里本来不表示任何字符,它们只在成对出现时才拼出一个增补平面字符。如果反转义时读到单独的一个代理项码点,比如只有高位没有低位,那它无法组成有效字符,页面会提示「孤立的代理项无法转成字符」并停下。同样地,码点写法里若给出大于 U+10FFFF 的值也非法,因为 UTF-16 最多编码到 U+10FFFF,这是这套编码的历史上限。
完整示例(数值仅作演示)
输入 柳泉 A,三种写法的输出如下,均由页面自身的算法算出,可与工具区结果逐字符核对。
- 四位写法:
\u67f3\u6cc9\u0020\u0041。四个字符各占一个四位写法,空格补零成 0020、字母 A 补零成 0041。 - 码点写法:
\u{67f3}\u{6cc9}\u{20}\u{41}。同样四个字符,但 20 与 41 不再补零,长度更短。 - 两位写法:
\u67f3\u6cc9\x20\x41。空格与字母 A 落在 U+00FF 内用两位,柳与泉超出范围降级为四位。 - 把上面任意一串粘回输入框、方向切到反转义,都会还原成
柳泉 A;其中两位写法里混着四位与两位两种形态,反转义同样能识别,说明解析是按出现的形态逐个判读的,不要求整串统一。 - 再加一个 emoji 验证代理项:输入单个笑脸(码点 U+1F600),四位写法给出
\ud83d\ude00,码点写法给出\u{1f600};把它还原时,四位写法的那两个代理项会被重新拼回同一个字符。
示例里的中文、空格与字母均为演示,用来对照三种写法的差别。
写法对比与常见字符编码表
下表并列三种转义写法与几种常被提到的同类记法,说明各自能表示的范围与适用语言。
| 写法 | 数字位数 | 可表示范围 | 适用语言 / 场景 |
|---|---|---|---|
| \uXXXX | 4 位十六进制 | BMP 内(U+0000~U+FFFF) | JS / JSON / Java 通用 |
| \u{XXXXX} | 1~6 位十六进制 | 全 Unicode(含 U+10FFFF) | ES6+ 才支持 |
| \xXX | 2 位十六进制 | 仅 U+0000~U+00FF | JS / C / Python |
| &#NNN; | 十进制 | HTML 数字实体 | HTML / XML |
| &#xHH; | 十六进制 | HTML 数字实体 | HTML / XML |
| %XX | 2 位十六进制 | 按 UTF-8 字节逐个转义 | URL 百分号编码 |
| \NNN | 八进制 | 仅 ASCII | C / Python2 |
| U+XXXX | 十六进制 | Unicode 标准记法 | 文档标注,不是代码 |
下表列出常见字符的码点、两种写法与 UTF-8 字节数;两位写法仅对落在 U+00FF 以内的字符成立,超出的会降级为四位写法。后四行默认折叠,点「加载更多」展开。
| 字符 | 码点 | 四位写法 | 码点写法 | UTF-8 字节 |
|---|---|---|---|---|
| A | U+0041 | \u0041 | \u{41} | 1 |
| a | U+0061 | \u0061 | \u{61} | 1 |
| 0 | U+0030 | \u0030 | \u{30} | 1 |
| 空格 | U+0020 | \u0020 | \u{20} | 1 |
| 柳 | U+67F3 | \u67f3 | \u{67f3} | 3 |
| 泉 | U+6CC9 | \u6cc9 | \u{6cc9} | 3 |
| é | U+00E9 | \u00e9 | \u{e9} | 2 |
| € | U+20AC | \u20ac | \u{20ac} | 3 |
| 中 | U+4E2D | \u4e2d | \u{4e2d} | 3 |
| 😀 | U+1F600 | \ud83d\ude00 | \u{1f600} | 4 |
| ¥ | U+00A5 | \u00a5 | \u{a5} | 2 |
| · | U+00B7 | \u00b7 | \u{b7} | 2 |
下表把几个字符用码元、码点与 UTF-8 字节三种口径并列,用来解释它们为什么常常对不上。
| 字符 | UTF-16 码元 | 码点 | UTF-8 字节 |
|---|---|---|---|
| 柳泉 A | 4 | 4 | 8 |
| 😀 | 2 | 1 | 4 |
| é | 1 | 1 | 2 |
| 中 | 1 | 1 | 3 |
| A | 1 | 1 | 1 |
结果边界、舍入与适用说明
- 反转义时,反斜杠 u 后不足四位会提示「转义序列不完整」,不会猜补零;大括号内出现孤立代理项(U+D800~U+DFFF)会提示无法转成有效字符。
- 码点写法里的数值超过 U+10FFFF 视为非法,因为 UTF-16 最多编码到这个上限。
- 转义方向选两位写法时,超出 U+00FF 的字符自动降级为四位写法,页面会在结果下方报告降级的字符个数。
- 转义不改变字符本身,只改变表示形式;反转义是它的逆运算,但只认本页支持的这几种写法,遇到未知转义一律原样保留。
- 示例中的十六进制统一用小写字母;大写写法在反转义时同样能识别。码点写法是 ES6 之后的语法,交给老环境可能解析失败。
- 所有换算在当前浏览器本地完成,输入与结果都不会上传到服务器。
常见问题
一个 emoji 在四位写法里为什么变成两段?
因为四位写法只能表示 BMP,而 emoji 的码点大于 U+FFFF。UTF-16 用一对代理项来表示它,所以会写成两个四位写法,例如笑脸是 \ud83d\ude00。想一个写法对应一个字符,请改用码点写法 \u{1f600}。
中文能不能用两位写法表示?
不能。两位写法只覆盖 U+0000 到 U+00FF,而汉字的最低码点也远在这之上。本页选两位写法时,中文会自动降级为四位写法,并在提示里告诉你有多少个字符发生了降级,而不是丢字符或输出乱码。
码点写法为什么在有的环境里报错?
反斜杠 u 加大括号是 ES6 才加入的语法,更早的浏览器、旧版 Node 以及部分构建工具链不认识它,会把它当普通文本或直接报错。跨环境通用时优先用四位写法。
反转义时提示孤立代理项是怎么回事?
代理项区间 U+D800 到 U+DFFF 本身不表示字符,它们在 UTF-16 里必须成对出现才拼出一个增补平面字符。如果你的输入里只有单独一个代理项码点,就无法组成有效字符,页面会停下并提示。
码元、码点、字节,到底该看哪个?
看目的。字符串长度限制通常按码元或字节算,字符个数按码点算,存储与传输按字节算。示例 柳泉 A 是四个码元、四个码点、八个 UTF-8 字节;一个笑脸则是两个码元、一个码点、四个字节,三种口径全都不一样。
转义和反转义能自动判断方向吗?
页面做成手动选择,因为同一段文本既可能是编码也可能刚好长得像编码。自动判断容易把普通文本里的反斜杠误当成转义,手动指定方向更稳;万一判错,换个方向重来即可。
这个工具免费吗?
免费,无需注册即可使用。
输入的数据安全吗?
安全。计算在当前浏览器本地完成,不会上传输入内容。