⌘K 切换工具
TEXT

乱码转换与还原

在浏览器内穷举可能的编码组合,还原乱码文本。

local
mojibake-fixer

🖥 Every candidate is decoded in your browser. Nothing is sent anywhere.

§01 关于此工具

概述

乱码不是损坏,而是用错误的表去读正确的字节。日本語 以 UTF-8 编码是九个字节;把这同样 的九个字节当作 Windows-1252 来读,就成了 日本語。什么都没丢失——只是解释错了, 把这一步倒回去,原文会被精确还原。

本工具先用「它很可能被误读成的编码」把您粘贴的文本重新编码回字节,再用「它实际上可能 使用的各种编码」逐一解码,然后为结果排序。第一名候选是产出有效 UTF-8 且不含替换字符 的那一组。

使用方法

  1. 粘贴乱码文本。
  2. 阅读带星号的第一名候选。
  3. 若不对,再看其他候选——每一个都标注了产出它的编码组合。

第一名候选通常正确的原因

排序不是对语言的猜测,而是利用 UTF-8 的一个结构性质:这种编码会自行申告序列长度。 首字节说明后面跟随几个后续字节,而每个后续字节都可被识别为后续字节。因此任意字节序列 几乎会立刻在按 UTF-8 解码时失败,浏览器的解码器会以替换字符报告这一失败。

所以当某个候选解码为 UTF-8 且完全没有替换字符时,那是有力证据而非偏好——说明这些字节 一开始就是有效的 UTF-8,而这恰恰是「在被某个环节按 Latin-1 读取之前本来是 UTF-8」的 文本所应具备的性质。候选还会按结果中是否仍残留乱码特征进一步排序,且只有能减少这些 特征的候选才会被提供。

不去动正确文本的原因

在产出任何候选之前,先检查输入是否具有乱码的特征:Latin-1 误读产生的特定字节对 (à /  / †/ ã 及其同类)、U+0080–U+009F 范围内的 C1 控制字符,以及 U+FFFD 替换字符。

三者皆无的文本会被报告为「干净」,且不提供任何候选。这一点很重要,因为对正确文本施加 这种变换是破坏性的。Grüßeseñor 是普通的德语与西班牙语;把它们当作乱码 去「修复」,得到的只会是无意义的字符串。总是给出候选的工具,恰恰在诱导这个错误。

无法恢复的情况

如果文本中含有 ? 或空方块,原始字节已经不在了。

这个区别值得说清楚。乱码保留字节而丢失解释,因此可逆。替换则丢失字节:转换器遇到目标 编码无法表示的字符时,会写入一个替换并丢弃原字符。任何工具都无法恢复它,因为已经没有 可供重新解释的对象。如果还能拿到源文件,那是唯一的出路。

双重乱码——乱码、保存、再乱码——有时可通过施加两次修复来恢复,但每一轮都会放大已有的 损失,结果会变差。

乱码从何而来

模式几乎总是「一个从未被声明的默认值」:

  • 在电子表格里打开的 CSV。 Windows 版 Excel 历来在没有 UTF-8 BOM 时假定 .csv 使用系统代码页,这就是满是重音符号的导出文件打开后成为乱码的原因。例如 café 会 变成 café
  • 未设置字符集的数据库连接。 数据存储得完全正确,是连接在做错误的转换,因此同样 的记录通过一个客户端可读、通过另一个客户端就是乱码。
  • 邮件主题行。 邮件头只允许 ASCII,因此非 ASCII 内容以会自行申告字符集的 RFC 2047 encoded-word 传输。日文主题至今仍常用 ISO-2022-JP,而假定 UTF-8 的解码器会把它们 全部变成乱码。
  • Content-Type 中没有 charset 的响应。 浏览器只能猜,而猜测结果取决于区域设置。
  • 压缩包里的旧文件名。 ZIP 没有可靠的字符集字段,因此在某个代码页下创建的文件名 会被用另一个代码页读取。

示例

  • 修复导入的 CSV — 粘贴一个受影响的字段以确定编码组合,然后用正确的编码重新导入, 而不是逐行修补。
  • 读取乱码的邮件主题 — 若是完整邮件,.eml 查看器会按邮件头 申告的字符集解码 encoded-word,ISO-2022-JP 也包含在内,因此主题无需修复即可正确阅读。
  • 定位处理链路的问题 — 产出修复结果的那一组编码,会告诉您转换在哪里出了错。 「以 UTF-8 写入、按 Windows-1252 读取」指向读取端缺少字符集声明,而不是数据本身有问题。
  • 检查日志输出 — 一个以某种编码输出日志的服务,配上一个以另一种编码读取的聚合系统, 只会让非 ASCII 的行变成乱码,因此在出现某个人名或来自已本地化系统的错误消息之前, 这个问题一直不会被注意到。

说明

候选由浏览器自带的 TextDecoder 解码,因此使用的是平台自身的编码表——本页面不附带任何 编码表。对旧式多字节编码的支持是 Encoding Standard 的要求,现行的所有浏览器都具备。

覆盖的编码在误读一侧为 windows-1252iso-8859-1windows-1251macintosh, 在原始一侧为 utf-8shift_jiseuc-jpiso-2022-jpgbkbig5euc-kr。 最多显示八个候选。

使用候选之前请务必先读一遍。样本较短时,多组编码都可能产出看似合理的结果,而结构性 检查无法告知这段文本本该是哪种语言。一切都在您的浏览器内完成——见隐私政策

FAQ
我的文本会被发送到某处吗?
不会。每个候选都由浏览器自带的 TextEncoder 与 TextDecoder 生成。没有任何内容离开页面,加载之后即可离线使用——这一点很重要,因为乱码文本通常来自真实文档、客户资料或日志。
为什么给出多个候选而不是一个答案?
因为不止一组编码组合能产出可读文本,而只有您知道这段文本本该是哪种语言。候选已排序,第一名是解码为有效 UTF-8 且不含替换字符的那一组——这是结构性质,不是对语言的猜测。
它说文本没有乱码,但我看着不对。
检测查找的是乱码的特征:Latin-1 误读产生的特定字节对、C1 控制字符,以及 U+FFFD 替换字符。三者皆无的文本,通过重新解码修复的可能性非常低,而强行给出候选只会破坏本来正确的文本。Grüße 与 señor 是正确拼写,不是乱码。
它说看起来是乱码,但没有候选更干净,怎么办?
通常是文本乱码了两次——错误编码、保存、再一次错误编码——或者经由本工具覆盖范围之外的编码。样本更长会有帮助,因为字节越多越容易分辨出正确的组合。已经含有替换字符的文本无法恢复,那部分信息已经丢失。
为什么问号和方块永远无法恢复?
因为原始字节已被丢弃。转换器遇到目标编码无法表示的字符时会替换为 U+FFFD 或占位字符,而这种替换不可逆。乱码之所以可以恢复,正是因为字节仍然存在、只有解释出了错。
覆盖哪些编码?
被误读为 windows-1252、iso-8859-1、windows-1251 或 macintosh;实际写入时为 utf-8、shift_jis、euc-jp、iso-2022-jp、gbk、big5 或 euc-kr。这覆盖了实务中的绝大多数情形,因为误读的那一侧几乎总是某种西欧单字节默认编码。