使用 PHP 将 CSV 转换为 JSON
Posted
技术标签:
【中文标题】使用 PHP 将 CSV 转换为 JSON【英文标题】:Convert CSV to JSON using PHP 【发布时间】:2015-03-22 23:25:23 【问题描述】:我正在尝试使用 php 将 CSV 文件转换为 JSON。
这是我的代码
<?php
date_default_timezone_set('UTC');
$today = date("n_j"); // Today is 1/23/2015 -> $today = 1_23
$file_name = $today.'.CSV'; // My file name is 1_23.csv
$file_path = 'C:\\Users\\bheng\\Desktop\\qb\\'.$file_name;
$file_handle = fopen($file_path, "r");
$result = array();
if ($file_handle !== FALSE)
$column_headers = fgetcsv($file_handle);
foreach($column_headers as $header)
$result[$header] = array();
while (($data = fgetcsv($file_handle)) !== FALSE)
$i = 0;
foreach($result as &$column)
$column[] = $data[$i++];
fclose($file_handle);
// print_r($result); // I see all data(s) except the header
$json = json_encode($result);
echo $json;
?>
print_r($result);
// 我看到所有数据
然后我json_encode($result);
并尝试显示它,但屏幕上根本没有显示任何内容。我看到的只是空白屏幕和 0 错误消息。
我做错了什么吗?有人能帮我吗 ?
添加
print_r($result);
的结果
Array (
[Inventory] => Array (
[0] => bs-0468R(20ug)
[1] => bs-1338R(1ml)
[2] => bs-1557G(no bsa)
[3] => bs-3295R(no BSA)
[4] => bs-0730R-Cy5"
[5] => bs-3889R-PE-Cy7"
[6] => 11033R
[7] => 1554R-A647
[8] => 4667
[9] => ABIN731018
[10] => Anti-DBNL protein
.... more ....
【问题讨论】:
如果您的print_r($result);
,请发布输出
@Rizier123 :我按照您的建议将其发布在我的帖子中!
【参考方案1】:
试试这样:
$file="1_23.csv";
$csv= file_get_contents($file);
$array = array_map("str_getcsv", explode("\n", $csv));
$json = json_encode($array);
print_r($json);
【讨论】:
str_getcsv
是什么?哇——你把整个事情变成了只有 5 行代码。令人印象深刻!
并且array_map将回调应用于给定数组php.net/manual/en/function.array-map.php的元素
不错。您的代码没有任何问题,但是当我这样做时 print_r($json);
- 屏幕上没有打印任何内容。你知道这是什么原因吗?
现在你明白我的意思了吗?
对象映射的自定义版本:php $dataFolder = realpath(dirname(__FILE__)); //echo $dataFolder; $file="$dataFolder/MonwooEcoleDeLaVie_Expressions-Expressions.csv"; $csv= file_get_contents($file); $csvLines = explode("\n", $csv); $indexes = str_getcsv(array_shift($csvLines)); $array = array_map(function ($e) use ($indexes) return array_combine($indexes, str_getcsv($e)); , $csvLines); $json = json_encode($array); print_r($json);
【参考方案2】:
data.csv
游戏,技能 宝藏猎人,pilipala 火箭发射器,bibobibo 火箭发动机,嘿嘿嘿嘿
要使用列名进行转换,我就是这样做的。
csv2json.php
<?php
if (($handle = fopen("data.csv", "r")) !== FALSE)
$csvs = [];
while(! feof($handle))
$csvs[] = fgetcsv($handle);
$datas = [];
$column_names = [];
foreach ($csvs[0] as $single_csv)
$column_names[] = $single_csv;
foreach ($csvs as $key => $csv)
if ($key === 0)
continue;
foreach ($column_names as $column_key => $column_name)
$datas[$key-1][$column_name] = $csv[$column_key];
$json = json_encode($datas);
fclose($handle);
print_r($json);
输出结果
[
"Game": "Treasure Hunter",
"Skill": "pilipala"
,
"Game": "Rocket Launcher",
"Skill": "bibobibo"
,
"Game": "Rocket Engine",
"Skill": "hehehohoho"
]
【讨论】:
【参考方案3】:你也可以试试这个方法。
<?php
function csvtojson($file,$delimiter)
if (($handle = fopen($file, "r")) === false)
die("can't open the file.");
$csv_headers = fgetcsv($handle, 4000, $delimiter);
$csv_json = array();
while ($row = fgetcsv($handle, 4000, $delimiter))
$csv_json[] = array_combine($csv_headers, $row);
fclose($handle);
return json_encode($csv_json);
$jsonresult = csvtojson("./doc.csv", ",");
echo $jsonresult;
【讨论】:
【参考方案4】:我遇到了类似的问题,我最终使用它在编码为 JSON 之前将数据递归转换为数组上的 UTF-8。
function utf8_converter($array)
array_walk_recursive($array, function(&$item, $key)
if(!mb_detect_encoding($item, 'utf-8', true))
$item = utf8_encode($item);
);
return $array;
来自: http://nazcalabs.com/blog/convert-php-array-to-utf8-recursively/
【讨论】:
【参考方案5】:如果您要转换动态 CSV 文件,您可以通过参数 (url=http://example.com/some.csv
) 传递 URL,它将显示最新版本:
<?php
// Lets the browser and tools such as Postman know it's JSON
header( "Content-Type: application/json" );
// Get CSV source through the 'url' parameter
if ( isset( $_GET['url'] ) )
$csv = explode( "\n", file_get_contents( $_GET['url'] ) );
$index = str_getcsv( array_shift( $csv ) );
$json = array_map(
function ( $e ) use ( $index )
return array_combine( $index, str_getcsv( $e ) );
, $csv
);
else
$json = "Please set the path to your CSV by using the '?url=' query string.";
// Output JSON
echo json_encode( $json );
【讨论】:
【参考方案6】:使用与@Whirlwind 解决方案类似的方法但返回更标准的 JSON 结果的替代解决方案(每个对象/记录都有命名字段):
// takes a string of CSV data and returns a JSON representing an array of objects (one object per row)
function convert_csv_to_json($csv_data)
$flat_array = array_map("str_getcsv", explode("\n", $csv_data));
// take the first array item to use for the final object's property labels
$columns = $flat_array[0];
for ($i=1; $i<count($flat_array)-1; $i++)
foreach ($columns as $column_index => $column)
$obj[$i]->$column = $flat_array[$i][$column_index];
$json = json_encode($obj);
return $json; // or just return $obj if that's a more useful return value
【讨论】:
这段代码给了我“警告:从空值创建默认对象”并且无法正确解析第 1 行标题的 3 行 CSV。【参考方案7】:这个问题现在已经很老了,但希望这对某人有所帮助,因为它似乎是我找到的最简单的例子,而且我知道这是开发人员作为初学者可能需要做的一件很常见的事情,并且很多答案都很有光泽超越魔法。
$file = storage_path('app/public/waitlist_users_test.csv'); //--> laravel helper, but you can use any path here
function csv_to_json($file)
// file() loads each row as an array value, then array map uses the 'str_getcsv' callback to
$csv = array_map('str_getcsv', file($file));
// array_walk - "walks" through each item of the array and applies the call back function. the & in "&row" means that alterations to $row actually change the original $csv array, rather than treating it as immutable (*sort of immutable...)
array_walk($csv, function(&$row) use ($csv)
// array_combine takes the header row ($csv[0]) and uses it as array keys for each column in the row
$row = array_combine($csv[0], $row);
);
array_shift($csv); # removes now very redundant column header --> contains 'col_1':'col_1', 'col_2':'col_2'...
$json = json_encode($csv);
return $json;
accept callback functions 的这些功能有很多神奇之处,上面似乎没有彻底解释。我是自学成才,多年来一直在编程,发现它经常被掩盖而没有详细说明回调是如何工作的,所以我将深入了解array_map('str_getcsv'、file($file)) 函数 - @ 987654325@,它将采用调用函数(在本例中为array_map)正在评估的任何(在本例中为数组)元素的值,并将其传递给回调函数,而无需显式传递变量-一旦你掌握了它的窍门就非常有帮助,但我发现它并没有经常得到彻底的解释,这让初学者不明白它为什么起作用,只是它有效。
我已经链接了上面的大部分内容,但这里有更多信息: str-getcsv do?Array WalkArray MapCallables/Callbacks
正如@MoonCactus 所说,file() 函数一次只加载 1 行,这有助于节省大型 .csv 文件的内存使用量。
另外,一些其他帖子使用explode - why not use explode() instead of str_getcsv() to parse rows? Because explode() would not treat possible enclosured parts of string or escaped characters correctly.
希望有人觉得这有帮助!
【讨论】:
【参考方案8】:接受的答案使用file_get_contents()
将整个文件作为字符串读取到内存中,然后使用explode()
使其成为数组。
但它可以做得更快、内存更小、更有用:
function ReadCsv($fn)
$lines= file($fn); // read file directly as an array of lines
array_pop($lines); // you can remove the last empty line (if required)
$json= json_encode(array_map("str_getcsv", $lines), JSON_NUMERIC_CHECK);
print_r($json);
注意:我在这里使用了JSON_NUMERIC_CHECK
以避免数字被双引号引用到字符串中。它还减少了输出大小,通常有助于另一方面的 javascript(例如计算或绘制数据)。不过要小心电话号码!
【讨论】:
【参考方案9】:我喜欢 @ian-d-miller 将数据转换为键/值样式格式的解决方案,但我一直遇到他的代码问题。
这对我有用:
function convert_CSV_to_JSON($csv_data)
// convert csv data to an array
$data = array_map("str_getcsv", explode("\n", $csv_data));
// use the first row as column headers
$columns = $data[0];
// create array to hold our converted data
$json = [];
// iterate through each row in the data
foreach ($data as $row_index => $row_data)
// skip the first row, since it's the headers
if($row_index === 0) continue;
// make sure we establish each new row as an array
$json[$row_index] = [];
// iterate through each column in the row
foreach ($row_data as $column_index => $column_value)
// get the key for each entry
$label = $columns[$column_index];
// add this column's value to this row's index / column's key
$json[$row_index][$label] = $column_value;
// bam
return $json;
用法:
// as is
$json = convert_CSV_to_JSON($csv);
// encoded
$json = json_encode($json);
【讨论】:
以上是关于使用 PHP 将 CSV 转换为 JSON的主要内容,如果未能解决你的问题,请参考以下文章