使用 str_getcsv 和 fgetcsv 将 CSV 数据转换为 PHP 数组时保留整数和浮点类型
Keep Integer and Float Types When Converting CSV Data to PHP Arrays With str_getcsv and fgetcsv
当使用 PHP
s str_getcsv
-函数数字将被视为字符串:
<?php
$csv = str_getcsv('0,1.2,"string"');
var_dump( $csv );
/* result: array(3) {
[0]=>string(1) "0"
[1]=>string(3) "1.2"
[2]=>string(6) "string"
} */
/* DESIRED result: array(3) {
[0]=>int(0)
[1]=>float(1.2)
[2]=>string(6) "string"
} */
fgetcsv
函数也是如此。如何克服这个问题而不在之后迭代数组并手动转换回每个值 - 可以这么说。
只是为了说清楚 - 我不是在寻求像这样的解决方法:
<?php
$csv = str_getcsv('0,1.2,"string"');
foreach ( $csv as &$v ) if ( is_numeric( $v ) ) $v += 0;
var_dump( $csv ); // desired result
因为我要处理相当多的数据,所以性能对我来说很重要。
我们可以将其作为副本关闭,但我很无聊。 json_decode
将解码为 int
、float
和 boolean
,并且比其他方法更快:
function str_getcsv_typed($string, $delimiter=",", enclosure='"', $escape = "\") {
return json_decode('[' . str_getcsv($string, $delimiter, enclosure, $escape) . ']');
}
function file_getcsv_typed($handle, $length=0, $delimiter=",", enclosure='"', $escape = "\") {
return json_decode('[' . fgetcsv($handle, $length, $delimiter, enclosure, $escape) . ']');
}
如果您的 CSV 中碰巧有 JSON 对象或数组格式的任何内容,那么它也可能会解码这些内容,也许不是您想要的。此外,如果有任何非法 JSON 字符或语法,它也会失败。
看来很遗憾,除了变通办法别无他法!有一些选择可以做到这一点,并且没有“唯一的方法”。根据每个用例,可能会有不同的解决方案。对于我的情况,我将使用以下代码。
<?php
$csv = '0,1.2,"string"';
json_decode( "[$csv]", true );
但请注意,这至少会在多行值时失败!
这里有一些测试:
<?php
$csv = '0,1.2,"string"';
var_dump(
json_decode( "[$csv]", true ) // works
, str_getcsv( $csv ) // converts everything to string
);
/*
array(3) { json_decode
[0]=>int(0)
[1]=>float(1.2)
[2]=>string(6) "string"
}
array(3) { str_getcsv
[0]=>
string(1) "0"
[1]=>
string(3) "1.2"
[2]=>
string(6) "string"
}
*/
$csv = '", as value in ,-separated csv"';
var_dump(
json_decode( "[$csv]", true ) // works also when separator is part of value
, str_getcsv( $csv ) // works also when separator is part of value but converts everything to string
);
/*
array(1) { json_decode
[0]=>string(29) ", as value in ,-separated csv"
}
array(1) { str_getcsv
[0]=>string(29) ", as value in ,-separated csv"
}
*/
$csv = '0,"value
with multiline"';
var_dump(
json_decode( "[$csv]", true ) // doesn't work as JSON can't handle multilines
, str_getcsv( $csv ) // works also with multilines but converts everything to string
);
/*
NULL json_decode
array(2) { str_getcsv
[0]=>string(1) "0"
[1]=>string(21) "value
with multiline"
}
*/
我最初问题的版本似乎是一种非常稳健的方法,因为它依赖于本机 str_getcsv
函数并随后转换为适当的类型。就性能而言,这对我来说听起来不太理想,但这应该只是处理非常重的字符串时的一个问题(对我来说就是这种情况)。
<?php
$csv = str_getcsv('0,1.2,"string"');
foreach ( $csv as &$v ) if ( is_numeric( $v ) ) $v += 0;
当使用 PHP
s str_getcsv
-函数数字将被视为字符串:
<?php
$csv = str_getcsv('0,1.2,"string"');
var_dump( $csv );
/* result: array(3) {
[0]=>string(1) "0"
[1]=>string(3) "1.2"
[2]=>string(6) "string"
} */
/* DESIRED result: array(3) {
[0]=>int(0)
[1]=>float(1.2)
[2]=>string(6) "string"
} */
fgetcsv
函数也是如此。如何克服这个问题而不在之后迭代数组并手动转换回每个值 - 可以这么说。
只是为了说清楚 - 我不是在寻求像这样的解决方法:
<?php
$csv = str_getcsv('0,1.2,"string"');
foreach ( $csv as &$v ) if ( is_numeric( $v ) ) $v += 0;
var_dump( $csv ); // desired result
因为我要处理相当多的数据,所以性能对我来说很重要。
我们可以将其作为副本关闭,但我很无聊。 json_decode
将解码为 int
、float
和 boolean
,并且比其他方法更快:
function str_getcsv_typed($string, $delimiter=",", enclosure='"', $escape = "\") {
return json_decode('[' . str_getcsv($string, $delimiter, enclosure, $escape) . ']');
}
function file_getcsv_typed($handle, $length=0, $delimiter=",", enclosure='"', $escape = "\") {
return json_decode('[' . fgetcsv($handle, $length, $delimiter, enclosure, $escape) . ']');
}
如果您的 CSV 中碰巧有 JSON 对象或数组格式的任何内容,那么它也可能会解码这些内容,也许不是您想要的。此外,如果有任何非法 JSON 字符或语法,它也会失败。
看来很遗憾,除了变通办法别无他法!有一些选择可以做到这一点,并且没有“唯一的方法”。根据每个用例,可能会有不同的解决方案。对于我的情况,我将使用以下代码。
<?php
$csv = '0,1.2,"string"';
json_decode( "[$csv]", true );
但请注意,这至少会在多行值时失败!
这里有一些测试:
<?php
$csv = '0,1.2,"string"';
var_dump(
json_decode( "[$csv]", true ) // works
, str_getcsv( $csv ) // converts everything to string
);
/*
array(3) { json_decode
[0]=>int(0)
[1]=>float(1.2)
[2]=>string(6) "string"
}
array(3) { str_getcsv
[0]=>
string(1) "0"
[1]=>
string(3) "1.2"
[2]=>
string(6) "string"
}
*/
$csv = '", as value in ,-separated csv"';
var_dump(
json_decode( "[$csv]", true ) // works also when separator is part of value
, str_getcsv( $csv ) // works also when separator is part of value but converts everything to string
);
/*
array(1) { json_decode
[0]=>string(29) ", as value in ,-separated csv"
}
array(1) { str_getcsv
[0]=>string(29) ", as value in ,-separated csv"
}
*/
$csv = '0,"value
with multiline"';
var_dump(
json_decode( "[$csv]", true ) // doesn't work as JSON can't handle multilines
, str_getcsv( $csv ) // works also with multilines but converts everything to string
);
/*
NULL json_decode
array(2) { str_getcsv
[0]=>string(1) "0"
[1]=>string(21) "value
with multiline"
}
*/
我最初问题的版本似乎是一种非常稳健的方法,因为它依赖于本机 str_getcsv
函数并随后转换为适当的类型。就性能而言,这对我来说听起来不太理想,但这应该只是处理非常重的字符串时的一个问题(对我来说就是这种情况)。
<?php
$csv = str_getcsv('0,1.2,"string"');
foreach ( $csv as &$v ) if ( is_numeric( $v ) ) $v += 0;