根据上面dan04 的评论,我们可以猜测字母“è”不知何故被误解为“Š”,然后对其应用了三重UTF-8 编码。
那么“è”是如何变成“Š”的呢?好吧,我有一种预感,最有可能的解释是在两个不同的 8 位字符集之间,所以我在 Wikipedia 上查找了一些常见的字符编码,并找到了一个匹配项:在CP850(以及其他各种相关的 8 位DOS 代码中)页,例如 CP851、CP853、CP857 等)字母“è”被编码为字节 0x8A,而在Windows-1252中则表示“Š”。
有了这些知识,我们可以用一个简单的 Unix shell 命令行重新创建这个曲折的错误编码链:
$ echo "Trois-Rivières" \
| iconv -t cp850 \
| iconv -f windows-1252 -t utf-8 \
| iconv -f iso-8859-1 -t utf-8 \
| iconv -f iso-8859-1 -t utf-8 \
| iconv -f ascii --byte-subst='\x%02X'
Trois-Rivi\xC3\x83\xC2\x85\xC3\x82\xC2\xA0res
在这里,第一个调用只是将字符串从我的本地字符编码(恰好是 UTF-8)转换为 CP850,最后一个调用只是使用 Python 样式的转义码iconv
对非 ASCII 字节进行编码。中间\xNN
的三个调用重新创建了应用于数据的实际重新编码步骤:首先从(假定的)Windows-1252 到 UTF-8,然后从 ISO-8859-1 到 UTF-8 两次。iconv
那么我们该如何解决呢?好吧,我们只需要反向应用相同的步骤:
$ echo -e 'Trois-Rivi\xC3\x83\xC2\x85\xC3\x82\xC2\xA0res' \
| iconv -f utf-8 -t iso-8859-1 \
| iconv -f utf-8 -t iso-8859-1 \
| iconv -f utf-8 -t windows-1252 \
| iconv -f cp850
Trois-Rivières
好消息是这个过程应该是可逆的。坏消息是原始文本中的任何“ü”、“ì”、“Å”、“É”和“Ø”字母都可能被不可逆转地损坏,因为在 CP850 中用于编码这些字母的字节在 Windows 中是未定义的-1252。(如果幸运的话,它们可能已被解释为这些字节在 ISO-8859-1 中表示的相同C1 控制代码,在这种情况下,原则上应该可以进行反向转换。我还没有弄清楚如何不过,说服iconv
他们这样做。)