将数组转换为csv
Posted
技术标签:
【中文标题】将数组转换为csv【英文标题】:Convert array into csv 【发布时间】:2011-04-25 10:08:35 【问题描述】:如何将数组转换为 CSV 文件?
这是我的数组:
stdClass Object
(
[OrderList_RetrieveByContactResult] => stdClass Object
(
[OrderDetails] => stdClass Object
(
[entityId] => 1025298
[orderId] => 10952
[orderName] => testing
[statusTypeId] => 4652
[countryCode] => AU
[orderType] => 1
[invoiceNumber] => 0
[invoiceDate] => 0001-01-01T00:00:00
[userID_AssignedTo] => 11711
[shippingAmount] => 8.95
[shippingTaxRate] => 0
[shippingAttention] =>
[shippingInstructions] =>
[shippingOptionId] => 50161
[discountCodeId] => 0
[discountRate] => 0
[totalOrderAmount] => 408.45
[directDebitTypeId] => 0
[directDebitDays] => 0
[isRecur] =>
[nextInvoiceDate] => 0001-01-01T00:00:00
[endRecurDate] => 0001-01-01T00:00:00
[cycleTypeID] => 1
[createDate] => 2010-10-08T18:40:00
[lastUpdateDate] => 2010-10-08T18:40:00
[deleted] =>
[products] => stdClass Object
(
[Product] => stdClass Object
(
[productId] => 674975
[productCode] =>
[productDescription] =>
[units] => 10
[unitPrice] => 39.95
[unitTaxRate] => 0
[totalProductPrice] => 399.5
[productName] => Acne Clearing Gel
)
)
[addresses] => stdClass Object
(
[Address] => stdClass Object
(
[addressTypeID] => 8
[addressLine1] => Cebu City
[city] => Cebu
[zipcode] => 6000
[state] =>
[countryCode] => PH
)
)
)
)
)
【问题讨论】:
您可能想用您的代码编写的任何语言来标记这个问题。这将帮助您获得更多关注您的问题的眼球。 :) 我认为没有办法在 CSV 中呈现多维性,是吗? 另见this solution,它将fputcsv()
与ob_start(); $df = fopen("php://output", 'w'); fclose($df); return ob_get_clean();
结合使用。
【参考方案1】:
我为此使用了以下功能;它改编自 fputscsv cmets 中的一个 man 条目。而且您可能想要展平该阵列;不知道如果你传入一个多维的会发生什么。
/**
* Formats a line (passed as a fields array) as CSV and returns the CSV as a string.
* Adapted from http://us3.php.net/manual/en/function.fputcsv.php#87120
*/
function arrayToCsv( array &$fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullTomysqlNull = false )
$delimiter_esc = preg_quote($delimiter, '/');
$enclosure_esc = preg_quote($enclosure, '/');
$output = array();
foreach ( $fields as $field )
if ($field === null && $nullToMysqlNull)
$output[] = 'NULL';
continue;
// Enclose fields containing $delimiter, $enclosure or whitespace
if ( $encloseAll || preg_match( "/(?:$delimiter_esc|$enclosure_esc|\s)/", $field ) )
$output[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
else
$output[] = $field;
return implode( $delimiter, $output );
【讨论】:
嗨,保罗,谢谢它对我帮助很大。你是最好的! :D 嗨,这对我有用。但我有一个问题,如何在 1 行之后创建一个新行?我在我的 for 循环中添加了一个计数器,如果它是第一个索引的结尾,我会追加一个新行,如 $output[$i] .= "\r\n";它创建了一个新行,但也在接下来的行中添加了一个新单元格。 有一种极端情况,如果您的$fields
数组中的最后一个值为空字符串,则将其丢弃。因此,如果您的数组有 3 个元素长并且最后一个元素是一个空字符串,那么您将在空字符串之前获得由 2 个分隔符分隔的值,而不是表示最后一个值为空所需的 3 个值。【参考方案2】:
我的解决方案要求数组的格式与问题中提供的不同:
<?
$data = array(
array( 'row_1_col_1', 'row_1_col_2', 'row_1_col_3' ),
array( 'row_2_col_1', 'row_2_col_2', 'row_2_col_3' ),
array( 'row_3_col_1', 'row_3_col_2', 'row_3_col_3' ),
);
?>
我们定义我们的函数:
<?
function outputCSV($data)
$outputBuffer = fopen("php://output", 'w');
foreach($data as $val)
fputcsv($outputBuffer, $val);
fclose($outputBuffer);
?>
然后我们将数据输出为 CSV:
<?
$filename = "example";
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=$filename.csv");
header("Pragma: no-cache");
header("Expires: 0");
outputCSV($data);
?>
我已经在几个项目中使用了它,并且效果很好。我应该注意到outputCSV
代码比我聪明,所以我确定我不是原作者。不幸的是,我不知道我是从哪里得到它的,所以我不能把它归功于谁。
【讨论】:
【参考方案3】:当您想在模板中创建和回显 CSV 时,kingjeffrey 对上述解决方案进行了轻微调整(即,大多数框架将启用输出缓冲,并且您需要在控制器中设置标头等。)
// Create Some data
<?php
$data = array(
array( 'row_1_col_1', 'row_1_col_2', 'row_1_col_3' ),
array( 'row_2_col_1', 'row_2_col_2', 'row_2_col_3' ),
array( 'row_3_col_1', 'row_3_col_2', 'row_3_col_3' ),
);
// Create a stream opening it with read / write mode
$stream = fopen('data://text/plain,' . "", 'w+');
// Iterate over the data, writting each line to the text stream
foreach ($data as $val)
fputcsv($stream, $val);
// Rewind the stream
rewind($stream);
// You can now echo it's content
echo stream_get_contents($stream);
// Close the stream
fclose($stream);
感谢上面的 Kingjeffrey 以及 blog post,我在其中找到了有关创建文本流的信息。
【讨论】:
此解决方案在不允许创建文件权限的情况下很有用【参考方案4】:function array_2_csv($array)
$csv = array();
foreach ($array as $item)
if (is_array($item))
$csv[] = array_2_csv($item);
else
$csv[] = $item;
return implode(',', $csv);
$csv_data = array_2_csv($array);
echo "<pre>";
print_r($csv_data);
echo '</pre>' ;
【讨论】:
您好 Paulrajj,非常感谢。你真的帮助我的问题。你真棒伙计! :D【参考方案5】:Paul 接受的回答很棒。我对此做了一个小的扩展,如果你有一个像这样的多维数组(这很常见),这非常有用:
Array
(
[0] => Array
(
[a] => "a"
[b] => "b"
)
[1] => Array
(
[a] => "a2"
[b] => "b2"
)
[2] => Array
(
[a] => "a3"
[b] => "b3"
)
[3] => Array
(
[a] => "a4"
[b] => "b4"
)
[4] => Array
(
[a] => "a5"
[b] => "b5"
)
)
所以我只是从上面取了 Paul 的函数:
/**
* Formats a line (passed as a fields array) as CSV and returns the CSV as a string.
* Adapted from http://us3.php.net/manual/en/function.fputcsv.php#87120
*/
function arrayToCsv( array &$fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false )
$delimiter_esc = preg_quote($delimiter, '/');
$enclosure_esc = preg_quote($enclosure, '/');
$output = array();
foreach ( $fields as $field )
if ($field === null && $nullToMysqlNull)
$output[] = 'NULL';
continue;
// Enclose fields containing $delimiter, $enclosure or whitespace
if ( $encloseAll || preg_match( "/(?:$delimiter_esc|$enclosure_esc|\s)/", $field ) )
$output[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
else
$output[] = $field;
return implode( $delimiter, $output );
并添加了这个:
function a2c($array, $glue = "\n")
$ret = [];
foreach ($array as $item)
$ret[] = arrayToCsv($item);
return implode($glue, $ret);
所以你可以打电话:
$csv = a2c($array);
如果你想要一个特殊的行尾,你可以使用可选参数“glue”。
【讨论】:
【参考方案6】:根据接受的答案添加一些改进。
-
PHP 7.0 严格输入
PHP 7.0 类型声明和返回类型声明
附件\r、\n、\t
即使 $encloseAll 为 TRUE,也不要包含空字符串
/**
* Formats a line (passed as a fields array) as CSV and returns the CSV as a string.
* Adapted from https://www.php.net/manual/en/function.fputcsv.php#87120
*/
function arrayToCsv(array $fields, string $delimiter = ';', string $enclosure = '"', bool $encloseAll = false, bool $nullToMysqlNull = false): string
$delimiter_esc = preg_quote($delimiter, '/');
$enclosure_esc = preg_quote($enclosure, '/');
$output = [];
foreach ($fields as $field)
if ($field === null && $nullToMysqlNull)
$output[] = 'NULL';
continue;
// Enclose fields containing $delimiter, $enclosure or whitespace, newline
$field = strval($field);
if (strlen($field) && ($encloseAll || preg_match("/(?:$delimiter_esc|$enclosure_esc|\s|\r|\n|\t)/", $field)))
$output[] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
else
$output[] = $field;
return implode($delimiter, $output);
【讨论】:
【参考方案7】:好吧,也许 4 年后有点晚了哈哈……但我一直在寻找对 CSV 执行 OBJECT 的解决方案,但是这里的大多数解决方案实际上是针对 ARRAY 到 CSV 的……
经过一番修改,这是我将对象转换为 CSV 的解决方案,我认为它非常简洁。希望这对其他人有帮助。
$resp = array();
foreach ($entries as $entry)
$row = array();
foreach ($entry as $key => $value)
array_push($row, $value);
array_push($resp, implode(',', $row));
echo implode(PHP_EOL, $resp);
请注意,要使$key => $value
起作用,您的object
的属性必须是公开的,不会获取私有的。
最终的结果是你会得到这样的结果:
blah,blah,blah
blah,blah,blah
【讨论】:
以上是关于将数组转换为csv的主要内容,如果未能解决你的问题,请参考以下文章