确保字符串是UTF-8编码的

时间:2013-03-02 16:14:10

标签: php csv utf-8

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

我有两个csv文件 example1.csv example2.csv 。我在notepad ++中都打开了,它显示了example1的ANSI编码和没有BOM的UTF-8(例如2)。

首先,我尝试使用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。

2 个答案:

答案 0 :(得分: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 setting,因此您绝对不应该依赖它并通过设置自己的检测顺序进入已知状态:

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?!?!?!

上述问题是,除非您为true参数传递$strict,否则检测到UTF-8会有点过于乐观。

那么,你真的可以做什么

这是最好的 - 检测编码的正确方法(只是在这里几乎无法使用复数):

$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. 假设文本在ISO-8859-X中,并根据与此编码对应的脚本的已知属性进行统计分析,以查看结果是否接近您的预期结果。如果它足够接近这个课程中的某些编码,那么你可以做出有根据的猜测。

答案 1 :(得分:-1)

检查utf8做这样的事情

if (mb_check_encoding(file_get_contents($file), 'UTF-8')) {
    // yup, all UTF-8
}