При использовании 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
поскольку я имею дело с довольно большой производительностью данных, это вещь в моем случае.
Мне очень нравится этот обходной путь.
@AbraCadaver уверен, что ты прав. csv является текстовым, но также может представлять числовые значения. Что не означает, что вы ошибаетесь, когда говорите: "Вы не можете"...
Я имел в виду, что вам придется что-то делать с данными после их получения из csv. Обходной путь @NigelRen выглядит лучшим. Просто напишите свою собственную функцию, которая включает в себя get csv и json_decode.
Ты сдался?
Вовсе нет @AbraCadaver. Я получил свое решение, а также более глубокое понимание. Тоже оставил ответ...
Мы можем закрыть это как дубликат, но мне скучно. 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, это также не удастся.
Можно ссылку на дуп? Есть много вопросов, касающихся разбора CSV-файлов и строк, но на самом деле ни один из них не относится к проблеме типа. stackoverflow.com/questions/9593765/… не особо про csv. Спасибо и +1 в любом случае... Не нравится, что вам скучно...
Это тот, если кто-то не найдет лучше.
Похоже, к сожалению, нет другого пути, кроме обходного пути! Есть несколько вариантов сделать это, и нет «единственного пути». В зависимости от каждого варианта использования могут быть разные решения. Для моей ситуации я буду использовать следующий код.
<?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;
Как преодолеть эту проблему, не перебирая впоследствии массив и не преобразовывая обратно каждое значение вручную. Вы не можете, CSV-файл является текстовым и обрабатывается как таковой.