以任何方式检测和删除(或修复)由于编码转换错误而导致的错误字符

时间:2011-03-04 01:30:16

标签: php character-encoding

我正在写一个解析器。我已经处理了所有编码转换以正确输出UTF-8,但有时源材料不正确。例如â€tm - 编码转换错误的结果。

我知道这是一个很长的镜头 - 但是有人知道由于糟糕的角色转换导致的常见字符串列表,或者任何事情,所以我不必建立自己的列表。

是的,我知道我很懒,但我读到的地方让我成为一名优秀的程序员?

1 个答案:

答案 0 :(得分:5)

tl; dr:请参阅最后两段。


我讨厌/喜欢编码问题。

我们正在查看Unicode Character 'RIGHT SINGLE QUOTATION MARK' (U+2019)的变异副本。该字符的字节序列为0xE2 0x80 0x99。在Windows-1252中,它对应于+ hat,Euro和商标符号(™)。我们看到的'tm'是将该商标符号进一步音译为ASCII t和ASCII m,0x74 0x6D,使我们最终破坏的字节序列为0xE2 0x80 0x74 0x6D

有可能+ hat-euro-t-m的实际表示已经是UTF-8。也就是说,+ hat是UTF-8序列,而Euro符号也是UTF-8序列,因为有人从已经编码不正确的Windows-1252文件复制并粘贴到UTF-8文档中。你会发现它比原来腐败中的四个字节要多得多。

解决此问题的一种方法是首先将这些字符的UTF-8编码转换回Windows-1252,然后在将其写回时将该Windows-1252字符串视为UTF-8。

为此,您可以将iconv//TRANSLIT标志一起使用:

$less_bad = iconv('UTF-8', 'Windows-1252//TRANSLIT', $bad);

这告诉iconv尝试将任何无法在Windows-1252中表示的字符转换为类似的字符。这种翻译不完美,会破坏Windows-1252中无法表示的任何合法的UTF-8字符。

获得Windows-1252字符串后,将其保存并以UTF-8形式提供。如果一切顺利,腐败应该消失,你不应该有任何问题。

是的,没错。

在这种特定情况下,正确序列的最后一个字节0x99已被错误的复制/粘贴分成两个字节。 你不会通过字符集编码箍跳来恢复它。

虽然跳跃可以对某些文档起作用,但你肯定会发现许多重新编码的东西。 最好的选择是进行字节级搜索和替换操作,寻找编码错误的序列,并用普通的ASCII或正确的UTF-8编码替换它们。很多编码错误的方法。例如,如果损坏源位于ISO-8859系列中,则最终损坏的序列可能会有所不同,或者最终的™可能不会在某些位置被瞄准tm。 / p>

保证字节级搜索和替换只会影响错误的重新编码序列,并且不会存在对不能在劣质字符集中表示的单编码UTF-8字符进行咀嚼的风险。它更安全,更快。


编辑:我完全没有意识到你已经在计划这样做了。 ;)不幸的是,我从未见过如此方便的名单。也许您应该发布和宣传您的工作,以便其他人可以从中受益。 yourcharacterencodingsucks.com可用!