file_get_contents 编码问题
Issue with file_get_contents encoding
我收到 file_get_contents(uri)
并返回一个我无法编码的 Json。
我尝试了几种编码,str_replace
但我不太明白问题出在哪里。
这是我 json 和 file_get_contents
的开始:
string(67702) "��{"localidades"
我知道它正在寻找未知字符,那是什么?是为了,但我不明白如何解决。
我已经试过了,但没有用
if(substr($s, 0, 2) == chr(0xFF).chr(0xFE)){
return substr($s,3);
}
else{
return $s;
}
}
这是xxd |从航站楼出发
00000000: fffe 7b00 2200 6c00 6f00 6300 6100 6c00 ..{.".l.o.c.a.l.
00000010: 6900 6400 6100 6400 6500 7300 2200 3a00 i.d.a.d.e.s.".:.
00000020: 2000 5b00 7b00 2200 6900 6400 4c00 6f00 .[.{.".i.d.L.o.
00000030: 6300 6100 6c00 6900 6400 6100 6400 2200 c.a.l.i.d.a.d.".
00000040: 3a00 2000 3300 2c00 2200 6c00 6f00 6300 :. .3.,.".l.o.c.
00000050: 6100 6c00 6900 6400 6100 6400 2200 3a00 a.l.i.d.a.d.".:.
00000060: 2000 2200 4200 7500 6500 6e00 6f00 7300 .".B.u.e.n.o.s.
00000070: 2000 4100 6900 7200 6500 7300 2200 2c00 .A.i.r.e.s.".,.
00000080: 2200 6900 6400 5000 7200 6f00 7600 6900 ".i.d.P.r.o.v.i.
00000090: 6e00 6300 6900 6100 2200 3a00 2000 2200 n.c.i.a.".:. .".
您尝试处理的文件采用 UTF-16 编码,PHP 本身不支持该文件。因此,为了处理它,您必须先删除 BOM header(前两个字节),然后使用 iconv 或 mbstring 将编码转换为 UTF-8。
你所拥有的是 UTF-16LE,其中每个代码点被编码为至少两个字节,甚至 "basic ASCII"。文档的前两个字节是字节顺序标记 [BOM],它声明这些代码点以何种字节顺序 [endian] 编码
$input = "\xff\xfe{\x00}\x00"; // UTF-16-LE with BOM
function convert_utf16($input, $charset=NULL) {
// if your data has no BOM you must explicitly define the charset.
if( is_null($charset) ) {
$bom = substr($input, 0, 2);
switch($bom) {
case "\xff\xfe":
$charset = "UTF-16LE";
break;
case "\xfe\xff":
$charset = "UTF-16BE";
break;
default:
throw new \Exception("No encoding specified, and no BOM detected");
break;
}
$input = substr($input, 2);
}
return mb_convert_encoding($input, "UTF-8", $charset);
}
$output = convert_utf16($input);
var_dump(
$output,
bin2hex($output),
json_decode($output, true)
);
输出:
string(2) "{}"
string(4) "7b7d"
array(0) {
}
还值得注意的是,使用 UTF-8 以外的任何编码 JSON 会使它无效 JSON,你应该告诉给你这些数据的人修复他们的应用程序。
您得到的是 UTF-16 LE
。开头的fffe
称为BOM
。您可以使用 iconv
:
$data = iconv( 'UTF-16', 'UTF-8', $data);
现在您有 UTF-8
和 BOM
。我认为它可以与 json_decode
一起使用,因为 PHP
似乎可以处理它。尽管如此,如果你想删除你应该删除的BOM
(见@Sammitch 评论),你也可以使用这个:
$data = preg_replace("/^pack('H*','EFBBBF')/", '', $data);
我重新创建了你文件的一部分,我得到了这个:
$data = file_get_contents('/var/www/html/utf16le.json');
$data = preg_replace("/^pack('H*','EFBBBF')/", '', iconv( 'UTF-16', 'UTF-8', $data));
print_r(json_decode($data));
输出:
stdClass Object
(
[localidades] => Array
(
[0] => stdClass Object
(
[idLocalidad] => 3
[localidad] => Buenos Aires
)
)
)
来自 xxd
:
我收到 file_get_contents(uri)
并返回一个我无法编码的 Json。
我尝试了几种编码,str_replace
但我不太明白问题出在哪里。
这是我 json 和 file_get_contents
的开始:
string(67702) "��{"localidades"
我知道它正在寻找未知字符,那是什么?是为了,但我不明白如何解决。
我已经试过了,但没有用
if(substr($s, 0, 2) == chr(0xFF).chr(0xFE)){
return substr($s,3);
}
else{
return $s;
}
}
这是xxd |从航站楼出发
00000000: fffe 7b00 2200 6c00 6f00 6300 6100 6c00 ..{.".l.o.c.a.l.
00000010: 6900 6400 6100 6400 6500 7300 2200 3a00 i.d.a.d.e.s.".:.
00000020: 2000 5b00 7b00 2200 6900 6400 4c00 6f00 .[.{.".i.d.L.o.
00000030: 6300 6100 6c00 6900 6400 6100 6400 2200 c.a.l.i.d.a.d.".
00000040: 3a00 2000 3300 2c00 2200 6c00 6f00 6300 :. .3.,.".l.o.c.
00000050: 6100 6c00 6900 6400 6100 6400 2200 3a00 a.l.i.d.a.d.".:.
00000060: 2000 2200 4200 7500 6500 6e00 6f00 7300 .".B.u.e.n.o.s.
00000070: 2000 4100 6900 7200 6500 7300 2200 2c00 .A.i.r.e.s.".,.
00000080: 2200 6900 6400 5000 7200 6f00 7600 6900 ".i.d.P.r.o.v.i.
00000090: 6e00 6300 6900 6100 2200 3a00 2000 2200 n.c.i.a.".:. .".
您尝试处理的文件采用 UTF-16 编码,PHP 本身不支持该文件。因此,为了处理它,您必须先删除 BOM header(前两个字节),然后使用 iconv 或 mbstring 将编码转换为 UTF-8。
你所拥有的是 UTF-16LE,其中每个代码点被编码为至少两个字节,甚至 "basic ASCII"。文档的前两个字节是字节顺序标记 [BOM],它声明这些代码点以何种字节顺序 [endian] 编码
$input = "\xff\xfe{\x00}\x00"; // UTF-16-LE with BOM
function convert_utf16($input, $charset=NULL) {
// if your data has no BOM you must explicitly define the charset.
if( is_null($charset) ) {
$bom = substr($input, 0, 2);
switch($bom) {
case "\xff\xfe":
$charset = "UTF-16LE";
break;
case "\xfe\xff":
$charset = "UTF-16BE";
break;
default:
throw new \Exception("No encoding specified, and no BOM detected");
break;
}
$input = substr($input, 2);
}
return mb_convert_encoding($input, "UTF-8", $charset);
}
$output = convert_utf16($input);
var_dump(
$output,
bin2hex($output),
json_decode($output, true)
);
输出:
string(2) "{}"
string(4) "7b7d"
array(0) {
}
还值得注意的是,使用 UTF-8 以外的任何编码 JSON 会使它无效 JSON,你应该告诉给你这些数据的人修复他们的应用程序。
您得到的是 UTF-16 LE
。开头的fffe
称为BOM
。您可以使用 iconv
:
$data = iconv( 'UTF-16', 'UTF-8', $data);
现在您有 UTF-8
和 BOM
。我认为它可以与 json_decode
一起使用,因为 PHP
似乎可以处理它。尽管如此,如果你想删除你应该删除的BOM
(见@Sammitch 评论),你也可以使用这个:
$data = preg_replace("/^pack('H*','EFBBBF')/", '', $data);
我重新创建了你文件的一部分,我得到了这个:
$data = file_get_contents('/var/www/html/utf16le.json');
$data = preg_replace("/^pack('H*','EFBBBF')/", '', iconv( 'UTF-16', 'UTF-8', $data));
print_r(json_decode($data));
输出:
stdClass Object
(
[localidades] => Array
(
[0] => stdClass Object
(
[idLocalidad] => 3
[localidad] => Buenos Aires
)
)
)
来自 xxd
: