Res*_*lov 2 php curl byte-order-mark utf-8
在我的脚本中,我使用 cURL 发送数据,并启用 CURLOPT_RETURNTRANSFER。响应是 json 编码的数据。当我尝试 json_decode 时,它返回 null。然后我发现响应在字符串的开头包含 utf-8 BOM 符号 ()。
有一些实验:
$data = $data = curl_exec($ch);
echo $data;
Run Code Online (Sandbox Code Playgroud)
结果是 {"field_1":"text_1","field_2":"text_2","field_3":"text_3"}
$data = $data = curl_exec($ch);
echo mb_detect_encoding($data);
Run Code Online (Sandbox Code Playgroud)
结果 - UTF-8
$data = $data = curl_exec($ch);
echo mb_convert_encoding($data, 'UTF-8', mb_detect_encoding($data));
// identical to echo mb_convert_encoding($data, 'UTF-8', 'UTF-8');
Run Code Online (Sandbox Code Playgroud)
结果 - {"field_1":"text_1","field_2":"text_2","field_3":"text_3"}
有帮助的一件事是删除前 3 个符号:
if (substr($data, 0, 3) == pack('CCC', 239, 187, 191)) {
$data = substr($data, 3);
}
Run Code Online (Sandbox Code Playgroud)
但是,如果还有另一个 BOM 呢?所以问题是:如何检测 cURL 响应的正确编码?或者如何检测 BOM 已到?或者也许如何使用 BOM 转换响应?
恐怕您已经自己找到了答案 - 这是个坏消息,因为我知道没有更好的答案。
BOM 不应该在那里,发件人有责任不一起发送它。
但我可以向您保证,BOM 要么存在,要么不存在,如果存在,就是您知道的那三个字节。
您可以稍微快一点并通过小的改动处理另一个 N BOM:
$__BOM = pack('CCC', 239, 187, 191);
// Careful about the three ='s -- they're all needed.
while(0 === strpos($data, $__BOM))
$data = substr($data, 3);
Run Code Online (Sandbox Code Playgroud)
第三方 BOM 检测器不会有任何不同。这样,即使稍后 cURL 开始剥离不需要的 BOM,您也会被覆盖。
一些 JSON 优化器和过滤器可能会决定输出需要 BOM。此外,也许更简单的是,编写生成 JSON 的脚本的人无意中在打开 PHP 标记之前包含了一个 BOM。Apache 不关心 BOM 是什么,在开始标记之前看到有数据,因此将其发送并从 PHP 流本身隐藏它。这有时也会导致“无法添加标题:输出已经开始”错误。
您可以验证 JSON 是否有效 UTF-8、BOM 或不是 BOM,但需要mb_string支持并且您必须使用严格模式来获取一些边缘情况:
if (false === mb_detect_encoding($data, 'UTF-8', true)) {
// JSON contains invalid sequences (erroneously NOT JSON encoded)
}
Run Code Online (Sandbox Code Playgroud)
我建议不要尝试纠正可能的编码错误;您可能会破坏自己的代码,并且还必须维护其他人的工作。