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

Upv*_*ote 6 php csv utf-8

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

我有两个csv文件example1.csvexample2.csv.我在notepad ++中都打开了,它显示了example1的ANSI编码和不带BOM的UTF-8.

首先,我尝试使用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))); 
Run Code Online (Sandbox Code Playgroud)

并为两个例子打印UTF-8.

Jon*_*Jon 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?
Run Code Online (Sandbox Code Playgroud)

所以你至少可以判断你的文字是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?!?!?!
Run Code Online (Sandbox Code Playgroud)

上面的问题是,除非你传递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"
Run Code Online (Sandbox Code Playgroud)

对于无效的UTF-8文本,可以做些什么?

除非你有关于该文本的带外信息,否则没什么.

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

  1. 查看文本开头是否有BOM.可能没有,即使在数学上你可能会误认为Unicode的单字节编码,但它值得一试.
  2. 看看它是否是UTF-16的味道.如果绝大多数偶数字节具有相同的值,那么您可能会看到UTF-16 LE.如果大多数奇数字节发生这种情况,你很可能会看到UTF-16 BE.不幸的是,在这两种情况下你都无法确定.
  3. 假设文本在ISO-8859-X中,并根据与此编码对应的脚本的已知属性进行统计分析,以查看结果是否接近您的预期结果.如果它对于本课程中的某些编码足够接近而对其他编码方式而言,则可以进行有根据的猜测.