找到自动编码检测的原因(UTF-8 vs Windows-1252)

find reason for automatic encoding detection (UTF-8 vs Windows-1252)

我有一个 CSV 文件,其中的内容是 UTF-8 编码的。然而,各种应用程序和系统错误地将 CSV 编码检测为 Windows-1252,这会破坏文件中的所有特殊字符(例如变音符号)。

我可以看到 Sublime Text(在 Windows 上)例如也会自动检测错误的 Windows-1252 编码,当第一次打开文件时,在应该是特殊字符的地方显示乱码成为.

当我选择 使用编码重新打开 » UTF-8 时,一切都会像预期的那样正常。

现在,为了找到错误的根源,我认为这可能有助于弄清楚为什么这些应用程序没有首先自动检测正确的编码。例如,可能某处存在编码错误的杂散字符。

有问题的 CSV 实际上是 Magento 2 安装自动生成的产品导出。最近字符编码坏了,我目前正试图弄清楚发生了什么——因此我调查了为什么这个导出被检测为 Windows-1252.

是否有任何可靠的方法可以弄清楚为什么像 Sublime Text 这样的应用程序的自动检测假定了错误的字符编码?

这就是我最后所做的,以找出文件未被检测为 UTF-8 的原因,即找到未以 UTF-8 编码的字符。由于 PHP 对我来说更容易获得,我决定简单地使用以下脚本,使用非常方便的 neitanod/forceutf8 库强制将任何非 UTF-8 转换为 UTF-8。

$before = file_get_contents('export.csv');
$after = \ForceUTF8\Encoding::toUTF8($before);
file_put_contents('export.fixed.csv', $after);

然后我使用像Beyond Compare这样的文件比较工具来比较两个生成的CSV,以便更容易地看到哪些字符最初不是用UTF-8编码的。

这反过来告诉我,只有一个特定的导出列受到影响。经过进一步调查,我发现该列的内容是在 PHP 中使用以下 preg_replace:

处理的
$value = preg_replace('/([^\pL0-9 -])+/', '', $value);

在正则表达式中使用 \p 有一个未知的副作用:所有特殊字符都被转换为另一种编码。一个快速的解决方案是在正则表达式上使用 u 标志(参见 regex pattern modifiers reference). This forces the resulting encoding of this preg_replace to be UTF-8. See also this answer.