6

在我的应用程序中,我读取了一个 csv 文件并向用户显示内容。但是编码有问题。

我有两个 csv 文件example1.csvexample2.csv。我都在记事本++中打开过,它显示了 example1 的 ANSI 编码和没有 BOM 的 UTF-8 的 example2。

首先,我尝试了 mb_detect_encoding函数来检测编码,但它在两种情况下都显示为 UTF-8,这是不正确的。

其次,我尝试使用utf8_encode将文件内容转换为 UTF-8 。这适用于 ANSI 文件。但是对于没有 BOM 文件的 UTF-8,它似乎被编码回 ANSI。它显示Ã而不是德语ß。其他特殊字符也一样。

我想确保在显示或处理内容之前始终采用 UTF-8 格式。那么我做错了什么吗?


这就是我使用 mb_detect_encoding 函数的方式:

$file_content = file_get_contents($_FILES['file']['tmp_name']);

die(var_dump( mb_detect_encoding($file_content))); 

它为这两个示例打印 UTF-8。

4

2 回答 2

10

成:另一个不便的真相

不可能以 100% 的准确度和/或置信度检测未知文本的编码。

在实践中,可能会出现各种结果:您可以非常确定 UTF-8 中的多语言文本将被正确检测到,而完全不可能检测出 ISO-8859 编码家族中的哪一个对应于一些文本——除非你愿意做统计分析,否则甚至不可能做出有根据的猜测!

我们必须处理什么?

有了这个,让我们看看你能做什么。首先,除非您将自定义工具带入战斗,否则您会受到mb_detect_encoding可以为您做的事情的限制。不幸的是,这并不是很多。姐妹函数的文档mb_detect_order指出:

mbstring 当前实现了以下编码检测过滤器。如果以下编码存在无效的字节序列,编码检测将失败。

UTF-8、UTF-7、ASCII、EUC-JP、SJIS、eucJP-win、SJIS-win、JIS、ISO-2022-JP。

对于 ISO-8859-X,mbstring 始终检测为 ISO-8859-X。

对于 UTF-16、UTF-32、UCS2 和 UCS4,编码检测将始终失败。

所以,打折日本编码,你基本上有能力区分 UTF-8、UTF-7 和 ASCII。您无法检测到 ISO-8859-X,因为如果您将其考虑在内,任何文本都将被“识别”为任何这些编码(即您将有 100% 的误报率 - 不好),并且包含 UTF 的组根本不支持-16。

不幸的是,坏消息并没有就此结束。编码顺序也很重要!由于以 UTF-7 或 ASCII 编码的文本也是有效的 UTF-8,将 UTF-8 放在候选列表的前面将确保这是您将获得的唯一结果——因此必须不惜一切代价避免它.

由于默认检测顺序取决于 php.ini设置,因此您绝对不应该依赖它并通过设置自己的检测顺序进入已知状态:

mb_detect_order('ASCII, UTF-8'); // I left UTF-7 out, but who cares?

所以你至少可以判断你的文本是 ASCII 还是 UTF-8,对吧?嗯,不。除非您特别要求,当您说“UTF-8”时,您是认真的:

$valid_utf8 = "\xC2\xA2";
$invalid_utf8 = "\xC2\x00";

mb_detect_order('UTF-8');
echo mb_detect_encoding($valid_utf8);   // "utf-8": correct
echo mb_detect_encoding($invalid_utf8); // "utf-8": WTF?!?!?!

上面的问题是,除非您传递参数,否则 UTF-8true$strict检测......有点过于乐观了。

好吧,您实际上可以用这件事做什么?

这是最好的——检测编码的正确方法(只是勉强在这里继续使用复数):

$valid_utf8 = "\xC2\xA2";
$invalid_utf8 = "\xC2\x00";
$ascii = "hello world";

mb_detect_order('ASCII, UTF-8');
echo mb_detect_encoding($valid_utf8, mb_detect_order(), true);   // OK: "utf-8"
echo mb_detect_encoding($invalid_utf8, mb_detect_order(), true); // OK: false
echo mb_detect_encoding($ascii, mb_detect_order(), true);        // OK: "ascii"

可以用不是有效 UTF-8 的文本做什么?

除非您有关于该文本的带外信息,否则很遗憾没有

好吧,这并不完全正确。在实践中你可以做一些事情:

  1. 看看文本开头是否有BOM。可能不会有,即使从数学上讲,您可能会将单字节编码误认为 Unicode,但值得一试。
  2. 看看是不是 UTF-16 的味道。如果绝大多数偶数字节具有相同的值,那么您可能正在查看 UTF-16 LE。如果大多数奇数字节发生这种情况,您可能正在查看 UTF-16 BE。不幸的是,在这两种情况下,你永远无法确定。
  3. Assume that the text is in ISO-8859-X and do statistical analysis based on known properties of the script that corresponds to this encoding to see if the result is close to what you would expect. If it's close enough for some encodings in this class and way off for the others you can make an educated guess.
于 2013-03-02T19:57:24.343 回答
-1

为了检查 utf8 做这样的事情

if (mb_check_encoding(file_get_contents($file), 'UTF-8')) {
    // yup, all UTF-8
}
于 2013-03-02T17:59:54.937 回答