PHP Conference Japan 2024

fputcsv

(PHP 5 >= 5.1.0、PHP 7、PHP 8)

fputcsv將行格式化為 CSV 並寫入檔案指標

說明

fputcsv(
    resource $stream,
    array $fields,
    string $separator = ",",
    string $enclosure = "\"",
    string $escape = "\\",
    string $eol = "\n"
): int|false

fputcsv() 將一行(以 fields 陣列傳遞)格式化為 CSV,並將其(以 eol 終止)寫入指定的 stream

參數

stream

檔案指標必須有效,並且必須指向由 fopen()fsockopen() 成功開啟的檔案(且尚未由 fclose() 關閉)。

fields

一個 string 的陣列。

separator

separator 參數設定欄位分隔符。它必須是單一位元組字元。

enclosure

enclosure 參數設定欄位包圍字元。它必須是單一位元組字元。

escape

escape 參數設定跳脫字元。它必須是單一位元組字元或空字串。空字串("")會停用專有的跳脫機制。

注意 通常 enclosure 字元在欄位內會透過重複自身來跳脫;然而,escape 字元可以用作替代方案。因此,對於預設參數值,""\" 具有相同的含義。除了允許跳脫 enclosure 字元外,escape 字元沒有其他特殊含義;它甚至不打算跳脫自身。

警告

自 PHP 8.4.0 起,依賴 escape 的預設值已棄用。它需要明確地以位置方式或透過使用具名引數來提供。

eol

可選的 eol 參數設定自訂的行尾序列。

警告

escape 設定為任何非空字串的值("")時,可能會導致 CSV 不符合 » RFC 4180,或無法在 PHP CSV 函式中往返。 escape 的預設值是 "\\",因此建議將其明確設定為空字串。預設值將在 PHP 未來的版本中變更,不會早於 PHP 9.0。

注意:

如果欄位中包含 enclosure 字元,它會透過重複自身來跳脫,除非它緊接在 escape 之後。

回傳值

回傳寫入字串的長度,失敗時回傳 false

錯誤/例外

如果 separatorenclosure 的長度不是一個位元組,則會拋出 ValueError

如果 escape 的長度不是一個位元組或空字串,則會拋出 ValueError

變更日誌

版本 說明
8.4.0 現在依賴 escape 的預設值已棄用。
8.1.0 已加入可選的 eol 參數。
7.4.0 escape 參數現在也接受空字串來停用專有的跳脫機制。

範例

範例 #1 fputcsv() 範例

<?php

$list
= array (
array(
'aaa', 'bbb', 'ccc', 'dddd'),
array(
'123', '456', '789'),
array(
'"aaa"', '"bbb"')
);

$fp = fopen('file.csv', 'w');

foreach (
$list as $fields) {
fputcsv($fp, $fields);
}

fclose($fp);
?>

上面的範例將以下內容寫入 file.csv

aaa,bbb,ccc,dddd
123,456,789
"""aaa""","""bbb"""

參見

新增註解

使用者貢獻的註解 25 則註解

339
MagicalTux at ooKoo dot org
17 年前
如果您需要將 CSV 檔案直接傳送到瀏覽器,而無需寫入外部檔案,您可以開啟輸出並在其上使用 fputcsv。

<?php
$out
= fopen('php://output', 'w');
fputcsv($out, array('this','is some', 'csv "stuff", you know.'));
fclose($out);
?>
64
bl at mindbench dot nl
17 年前
如果您需要將輸出儲存到變數中(例如,在框架內使用),您可以寫入暫時的記憶體封裝器並檢索其內容

<?php
// 輸出最多 5MB 的內容會保留在記憶體中,如果超過這個大小,則會自動寫入臨時檔案
$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');

fputcsv($csv, array('blah','blah'));

rewind($csv);

// 將所有內容放入變數中
$output = stream_get_contents($csv);
?>
46
mikhail dot galanin at yahoo dot com
7 年前
有時候將 CSV 行以字串形式取得會很有用。例如,將其儲存在某處,而不是檔案系統中。

<?php
function csvstr(array $fields) : string
{
$f = fopen('php://memory', 'r+');
if (
fputcsv($f, $fields) === false) {
return
false;
}
rewind($f);
$csv_line = stream_get_contents($f);
return
rtrim($csv_line);
}
?>
79
Anonymous
9 年前
如果您想要製作 Excel 可用的 UTF-8 檔案,請使用這個方法

$fp = fopen($filename, 'w');
//新增 BOM 以修正 Excel 中的 UTF-8 問題
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
34
reinhold dot egenter at gmail dot com
4 年前
請注意,fputcsv 並非總是會用 enclosure 字元將字串包住。

<?php
$fh
= fopen('file.csv', 'w');

$a = [ 'One 1', 'Two', 'Three 3' ];

fputcsv($fh, $a, "\t");

fclose($fh);
?>

結果檔案會包含以下這行
"One 1" Two "Three 3"

看起來只有包含以下至少一個字元的字串才会被包住

- 分隔符號字元
- 包圍字元
- 跳脫字元
- \n (換行符號)
- \r (歸位符號)
- \t (tab)
- 空白

我希望這能為您省下我花費一個小時才弄清楚這個行為的時間。
1
php at richardneill dot org
10 個月前
為了與標準 (RFC-4180) CSV 檔案達到最大的相容性,請記得停用專屬的跳脫機制。也就是說,將可選的第五個參數設定為 "" (空字串)。
1
johannes dot kingma at gmail dot com
3 年前
在所有這些情況下,您都需要一個具有自訂記錄分隔功能的無錯誤 CSV 寫入器

<?php
/**
* 自訂 fputcsv
* @param int $handle 檔案控制代碼
* @param mixed[] $fields 要寫入的值陣列
* @param string $delimiter 欄位分隔符號
* @param string $enclosure 欄位包圍符號
* @param string $escape_char 跳脫欄位中的包圍符號字元
* @param string $record_seperator
* @return int 寫入的字元數
*/
function _fputcsv($handle, $fields, $delimiter = ",", $enclosure = '"', $escape_char = "\\", $record_seperator = "\r\n")
{
$result = [];
foreach (
$fields as $field) {
$result[] = $enclosure . str_replace($enclosure, $escape_char . $enclosure, $field) . $enclosure;
}
return
fwrite($handle, implode($delimiter, $result) . $record_seperator);
}
?>
41
alex /-\-l- windeagle DOT org
15 年前
以 TAB 分隔。

使用 fputcsv 輸出以 tab 分隔的 CSV 有點棘手,因為分隔符號欄位只接受一個字元。
答案是使用 chr() 函數。tab 的 ascii 碼是 9,所以 chr(9) 會傳回一個 tab 字元。

<?php
fputcsv
($fp, $foo, '\t'); // 無效
fputcsv($fp, $foo, ' '); // 無效

fputcsv($fp, $foo, chr(9)); // 有效
?>

==================

應該是
<?php
fputcsv
($fp, $foo, "\t");
?>
您只是忘記單引號是文字,表示您在那裡輸入的任何內容都會原封不動地顯示,因此 '\t' 會與 't' 相同,因為在這種情況下 \ 只會用於跳脫,但如果您使用雙引號,則可以正常運作。
12
Biniam Nigusse
8 年前
以下是如何在將陣列轉換為 csv 檔案時解決編碼問題的解決方案。

$fp = fopen('php://memory', 'w');
//新增 BOM 以修正 Excel 中的 UTF-8 問題
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
// 輸出欄標題
//fputcsv($fp, array('Topic', 'Title', 'URL', 'Keywords', 'Score', 'FB_count', 'TW_count', '|'));
if(isset($trend)){
foreach ( $trend as $myField ){
fputcsv($fp, $myField, '|');
}
}
23
jamie at agentdesign dot co dot uk
13 年前
公用函數,用於將 mysql 查詢輸出到 csv,並可選擇寫入檔案或將 csv 附件傳回瀏覽器。

<?php
function query_to_csv($db_conn, $query, $filename, $attachment = false, $headers = true) {

if(
$attachment) {
// 發送回應標頭至瀏覽器
header( 'Content-Type: text/csv' );
header( 'Content-Disposition: attachment;filename='.$filename);
$fp = fopen('php://output', 'w');
} else {
$fp = fopen($filename, 'w');
}

$result = mysql_query($query, $db_conn) or die( mysql_error( $db_conn ) );

if(
$headers) {
// 輸出標題列 (如果至少存在一列)
$row = mysql_fetch_assoc($result);
if(
$row) {
fputcsv($fp, array_keys($row));
// 將指標重設回開頭
mysql_data_seek($result, 0);
}
}

while(
$row = mysql_fetch_assoc($result)) {
fputcsv($fp, $row);
}

fclose($fp);
}

// 使用函數
$sql = "SELECT * FROM table";
// $db_conn 應該是有效的資料庫連線處理

// 輸出為附件
query_to_csv($db_conn, $sql, "test.csv", true);

// 輸出至檔案系統
query_to_csv($db_conn, $sql, "test.csv", false);
?>
10
soapergem at gmail dot com
15 年前
我建立了一個函數,用於快速產生可與 Microsoft 應用程式搭配使用的 CSV 檔案。在實務上,我學到了一些關於產生 CSV 檔案的眉角,這些事情並非總是顯而易見。首先,由於 PHP 通常是基於 *nix 系統,因此換行符號始終是 \n 而不是 \r\n 是很合理的。然而,某些 Microsoft 程式(我指的是你,Access 97),除非每一行的結尾都是 \r\n,否則將無法正確識別 CSV 檔案。因此,此函數會相應地變更換行符號。其次,如果 CSV 檔案的第一個欄位標題/值以大寫 ID 開頭,某些 Microsoft 程式(咳咳,Excel 2007)會將檔案解釋為 SYLK 格式而非 CSV 格式,如這裡所述:http://support.microsoft.com/kb/323626

此函數也會處理這個問題,方法是強制將第一個值以引號括起來(當它沒有自動發生時)。如果需要,修改此函數以使用其他分隔符號相當簡單,我將其留給讀者自行練習。因此,簡而言之,此函數用於以一種安全的方式將 CSV 資料輸出到 CSV 檔案,以便與 Windows 應用程式一起使用。它採用兩個參數 + 一個可選參數:應儲存檔案的位置、資料列的陣列,以及欄位標題的可選陣列。(從技術上講,您可以省略標題陣列,而僅將其作為資料的第一列,但在實務中,將這些資料儲存在不同的陣列中通常很有用。)

<?php

function mssafe_csv($filepath, $data, $header = array())
{
if (
$fp = fopen($filepath, 'w') ) {
$show_header = true;
if ( empty(
$header) ) {
$show_header = false;
reset($data);
$line = current($data);
if ( !empty(
$line) ) {
reset($line);
$first = current($line);
if (
substr($first, 0, 2) == 'ID' && !preg_match('/["\\s,]/', $first) ) {
array_shift($data);
array_shift($line);
if ( empty(
$line) ) {
fwrite($fp, "\"{$first}\"\r\n");
} else {
fwrite($fp, "\"{$first}\",");
fputcsv($fp, $line);
fseek($fp, -1, SEEK_CUR);
fwrite($fp, "\r\n");
}
}
}
} else {
reset($header);
$first = current($header);
if (
substr($first, 0, 2) == 'ID' && !preg_match('/["\\s,]/', $first) ) {
array_shift($header);
if ( empty(
$header) ) {
$show_header = false;
fwrite($fp, "\"{$first}\"\r\n");
} else {
fwrite($fp, "\"{$first}\",");
}
}
}
if (
$show_header ) {
fputcsv($fp, $header);
fseek($fp, -1, SEEK_CUR);
fwrite($fp, "\r\n");
}
foreach (
$data as $line ) {
fputcsv($fp, $line);
fseek($fp, -1, SEEK_CUR);
fwrite($fp, "\r\n");
}
fclose($fp);
} else {
return
false;
}
return
true;
}

?>
13
nate at example dot com
16 年前
好的,在試用了一段時間後,我確信以下替代函數在所有情況下都能正常運作,包括原生 fputcsv 函數會失敗的情況。如果 fputcsv 對您來說無法正常運作(特別是使用 mysql csv 導入時),請嘗試將此函數作為替代方案使用。

傳入的參數與 fputcsv 完全相同,但我添加了一個額外的 $mysql_null 布林值,允許將 php 的 null 值轉換為可插入 mysql 的 null 值(預設情況下,此附加功能已停用,因此與 fputcsv 的運作方式相同 [除了這個函數可以正常運作!])。

<?php

function fputcsv2 ($fh, array $fields, $delimiter = ',', $enclosure = '"', $mysql_null = false) {
$delimiter_esc = preg_quote($delimiter, '/');
$enclosure_esc = preg_quote($enclosure, '/');

$output = array();
foreach (
$fields as $field) {
if (
$field === null && $mysql_null) {
$output[] = 'NULL';
continue;
}

$output[] = preg_match("/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field) ? (
$enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure
) : $field;
}

fwrite($fh, join($delimiter, $output) . "\n");
}

// 要使用的 _EXACT_ LOAD DATA INFILE 命令
// (如果您在上面為 $delimiter
// 和/或 $enclosure 傳入不同的值,也請在此處進行變更;
// 但是 _保持 ESCAPED BY 空白!_).
/*
LOAD DATA INFILE
'/path/to/file.csv'

INTO TABLE
my_table

FIELDS TERMINATED BY
','

OPTIONALLY ENCLOSED BY
'"'

ESCAPED BY
''

LINES TERMINATED BY
'\n'
*/

?>
10
ifunk
17 年前
我從 PHP 原始碼轉換了這個函數。這完全複製了 PHP5 的功能,而這裡的其他範例則沒有。

<?php

if (!function_exists('fputcsv')) {

function
fputcsv(&$handle, $fields = array(), $delimiter = ',', $enclosure = '"') {
$str = '';
$escape_char = '\\';
foreach (
$fields as $value) {
if (
strpos($value, $delimiter) !== false ||
strpos($value, $enclosure) !== false ||
strpos($value, "\n") !== false ||
strpos($value, "\r") !== false ||
strpos($value, "\t") !== false ||
strpos($value, ' ') !== false) {
$str2 = $enclosure;
$escaped = 0;
$len = strlen($value);
for (
$i=0;$i<$len;$i++) {
if (
$value[$i] == $escape_char) {
$escaped = 1;
} else if (!
$escaped && $value[$i] == $enclosure) {
$str2 .= $enclosure;
} else {
$escaped = 0;
}
$str2 .= $value[$i];
}
$str2 .= $enclosure;
$str .= $str2.$delimiter;
} else {
$str .= $value.$delimiter;
}
}
$str = substr($str,0,-1);
$str .= "\n";
return
fwrite($handle, $str);
}

}

?>
1
perske at muenster dot de
7 年前
若要產生符合 RFC 4180 標準的輸出,請勿使用 fputcsv,而是手動編碼,如下所示

function rfccsv($arr){
foreach($arr as &$a){
$a=strval($a);
if(strcspn($a,",\"\r\n")<strlen($a))$a='"'.strtr($a,array('"'=>'""')).'"';
}
return implode(',',$arr);
}
echo rfccsv(array(.....))."\n";
1
julian at polygon dot red
4 年前
如果您不想將字串括起來(因為您自己管理或您的內容已經被括起來了?),請注意您不能將空括號傳遞給 fputcsv。該函數需要該參數有一個字元。chr(0) 效果很好

fputcsv($handle, $fields, ",", chr(0));
2
drew at zitnay dot com
20 年前
[由 danbrown AT php DOT net 編輯:這是一個修訂後的函數,由作者進行了一些錯誤修復和改進。原始的函數範例由 arthur AT mclean DOT ws 編寫,並由 arthur AT korn DOT ch 重新編寫。]

- 當呼叫 str_replace() 時,您必須將傳回值賦予 $cell,否則不會儲存任何內容

- 當使用 strchr() 時,您應該明確檢查 !== FALSE,否則它會將傳回值 0(在字串位置 0 找到字元)視為 FALSE

- Excel 似乎不僅會引用包含逗號的欄位,還會引用包含引號的欄位,因此我為引號新增了另一個 strchr();我並不是說 Microsoft 知道正確的方法,但對我來說似乎是合理的

- 原始函數在每個逗號後放置一個空格;這可能是合法的,我不知道,但我從未見過(而且我認為不是,因為那麼您如何表示希望欄位以空格開頭,而不是用引號括起來?)

- 原始函數沒有正確傳回輸出的資料長度

這是經過一些修正的函數

<?php
function fputcsv($handle, $row, $fd=',', $quot='"')
{
$str='';
foreach (
$row as $cell) {
$cell=str_replace(Array($quot, "\n"),
Array(
$quot.$quot, ''),
$cell);
if (
strchr($cell, $fd)!==FALSE || strchr($cell, $quot)!==FALSE) {
$str.=$quot.$cell.$quot.$fd;
} else {
$str.=$cell.$fd;
}
}

fputs($handle, substr($str, 0, -1)."\n");

return
strlen($str);
}
?>

Drew
2
simeonl at dbc dot co dot nz
14 年前
一般來說,我發現自己想要取得的是字串結果,而不是寫入檔案。特別是,我想要產生一個 CSV 檔案,其行尾符號 (EOL) 可能與我產生它的伺服器上的不同。這是我如何在不重寫 fputcsv 的情況下解決這個問題的方法。

<?php
function sputcsv($row, $delimiter = ',', $enclosure = '"', $eol = "\n")
{
static
$fp = false;
if (
$fp === false)
{
$fp = fopen('php://temp', 'r+'); // 請參閱 https://php.dev.org.tw/manual/en/wrappers.php.php - 是的,結尾有 2 個 '.php'。
// 注意:您對 'php://temp' 讀取/寫入的任何內容都特定於此檔案控制代碼
}
else
{
rewind($fp);
}

if (
fputcsv($fp, $row, $delimiter, $enclosure) === false)
{
return
false;
}

rewind($fp);
$csv = fgets($fp);

if (
$eol != PHP_EOL)
{
$csv = substr($csv, 0, (0 - strlen(PHP_EOL))) . $eol;
}

return
$csv;
}

// 測試
$rows = array
(
array(
'blue, sky', 'green, lime', 'red', 'black'),
array(
'white', 'gold', 'purple, imperial', 'grey, slate'),
array(
'orange, burnt', 'pink, hot', 'violet', 'indigo'),
);

if (
PHP_EOL == "\r\n")
{
$eol = "\n";
}
else
{
$eol = "\r\n";
}

foreach(
$rows as $row)
{
echo
nl2br(sputcsv($row, ',', '"', $eol));
}
?>

測試結果應產生如下所示的內容

"blue, sky","green, lime",red,black
white,gold,"purple, imperial","grey, slate"
"orange, burnt","pink, hot",violet,indigo
1
mike at fatica dot net
10 年前
我們有一個函式可以寫入單行 CSV。我注意到啟用 auto_detect_line_endings 後,fputcsv 不會在檔案末尾寫入換行符。

啟用 auto_detect_line_endings 後,會變更 fputcsv 的行為以包含換行符。
2
encode
3 年前
關於 Excel 和 UTF-16LE 編碼

為了完全相容於 Excel(變音符號、西里爾字母、中文字母等),需要將 .csv 編碼為 UTF-16LE,使用 Tab 字元 (\t) 作為分隔符,並在檔案開頭包含 UTF-16LE BOM。

然而,這無法透過簡單地編碼 putcsv 的輸入來完成,因為分隔符和封閉符號仍將以預設編碼寫入,並且 fputcsv 不會接受 UTF-16 編碼的分隔符/封閉符號。

簡單的解決方案是使用逸出等功能來自行實作 fputcsv,或在事後編碼產生的 .csv 檔案。
0
alanzhang717 at gmail dot com
11 年前
當您使用 fputcsv 輸出 csv 時,如果包含任何中文字符,您可能會得到亂碼。然後您需要正確設定編碼。

fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // 只需加入這一行
fputcsv($fp, ...);
0
R dot Mansveld at Spider-IT dot de
11 年前
受到 boonerunner 函式的啟發,我編寫了一個更小、更快、更靈活且使用更少記憶體的函式。
我也重新命名了它以避免衝突或覆寫 PHP 函式,並為第 3 個和第 4 個參數賦予了與 fputcsv() 使用的預設值。

此函式會將所有文字值放在 $enclosure 中,同時將值中的 $enclosure 加倍,並保持數值不變。
但是如果數值中存在 $delimiter,則此值也會放在 $enclosure 中(如果您使用點作為 $delimiter,可能會發生這種情況)。

function fwritecsv($handle, $fields, $delimiter = ',', $enclosure = '"') {
# 檢查 $fields 是否為陣列
if (!is_array($fields)) {
return false;
}
# 遍歷資料陣列
for ($i = 0, $n = count($fields); $i < $n; $i ++) {
# 僅「更正」非數值
if (!is_numeric($fields[$i])) {
# 複製值內的 $enclusure 並將值放在 $enclosure 中
$fields[$i] = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $fields[$i]) . $enclosure;
}
# 如果 $delimiter 是點 (.),則也更正數值
if (($delimiter == '.') && (is_numeric($fields[$i]))) {
# 將值放在 $enclosure 中
$fields[$i] = $enclosure . $fields[$i] . $enclosure;
}
}
# 將資料陣列與 $delimiter 結合,並寫入檔案
$line = implode($delimiter, $fields) . "\n";
fwrite($handle, $line);
# 傳回寫入資料的長度
return strlen($line);
}
0
jon+dontspamme at phpsitesolutions dot com
16 年前
我發現 PHP 4 的 fputcsv 範例缺少一件事,那就是在 $enclosure 值為引號時的正確處理方式(如果引號在欄位中傳遞,並且以斜線分隔,則此處提交的函式將無法正確處理)。

我修改後的函式是使用 fputcsv 的實際 PHP5 原始碼建置的,並額外增加了正確回應正在處理的欄位中是否存在分隔引號的功能。

<?php
if (!function_exists('fputcsv')) {
function
fputcsv(&$handle, $fields = array(), $delimiter = ',', $enclosure = '"') {

// 健全性檢查
if (!is_resource($handle)) {
trigger_error('fputcsv() 預期參數 1 為資源(resource),但給定的是 ' .
gettype($handle) . ' ', E_USER_WARNING);
return
false;
}

if (
$delimiter!=NULL) {
if(
strlen($delimiter) < 1 ) {
trigger_error('分隔符號必須是單一字元', E_USER_WARNING);
return
false;
}elseif(
strlen($delimiter) > 1 ) {
trigger_error('分隔符號必須是單一字元', E_USER_NOTICE);
}

/* 使用字串的第一個字元 */
$delimiter = $delimiter[0];
}

if(
$enclosure!=NULL ) {
if(
strlen($enclosure) < 1 ) {
trigger_error('包圍符號必須是單一字元', E_USER_WARNING);
return
false;
}elseif(
strlen($enclosure) > 1 ) {
trigger_error('包圍符號必須是單一字元', E_USER_NOTICE);
}

/* 使用字串的第一個字元 */
$enclosure = $enclosure[0];
}

$i = 0;
$csvline = '';
$escape_char = '\\';
$field_cnt = count($fields);
$enc_is_quote = in_array($enclosure, array('"',"'"));
reset($fields);

foreach(
$fields AS $field ) {

/* 將包含分隔符號、包圍符號或換行的欄位包圍起來 */
if( is_string($field) && (
strpos($field, $delimiter)!==false ||
strpos($field, $enclosure)!==false ||
strpos($field, $escape_char)!==false ||
strpos($field, "\n")!==false ||
strpos($field, "\r")!==false ||
strpos($field, "\t")!==false ||
strpos($field, ' ')!==false ) ) {

$field_len = strlen($field);
$escaped = 0;

$csvline .= $enclosure;
for(
$ch = 0; $ch < $field_len; $ch++ ) {
if(
$field[$ch] == $escape_char && $field[$ch+1] == $enclosure && $enc_is_quote ) {
continue;
}elseif(
$field[$ch] == $escape_char ) {
$escaped = 1;
}elseif( !
$escaped && $field[$ch] == $enclosure ) {
$csvline .= $enclosure;
}else{
$escaped = 0;
}
$csvline .= $field[$ch];
}
$csvline .= $enclosure;
} else {
$csvline .= $field;
}

if(
$i++ != $field_cnt ) {
$csvline .= $delimiter;
}
}

$csvline .= "\n";

return
fwrite($handle, $csvline);
}
}
?>
-2
David Thomas
13 年前
將 XML 字串輸出為 CSV,第一列作為欄位標頭

<?php

// 在此例中,XML 的格式如下:
// <records>
// <record>...</record>
// <record>...</record>
// </records>

if($xml = simplexml_load_string($string)){
// 在記憶體中保留最多 12MB,若超過則寫入暫存檔
$file = fopen('php://temp/maxmemory:'. (12*1024*1024), 'r+');
if(
$row = get_object_vars($xml->record[0])){ // 第一筆記錄
// 第一列包含欄位標頭的值
foreach($row as $key => $value){
$header[] = $key;
}
fputcsv($file, $header,',','"');
foreach (
$xml->record as $record) {
fputcsv($file, get_object_vars($record),',','"');
}
rewind($file);
$output = stream_get_contents($file);
fclose($file);
return
$output;
}else{
return
'';
}
}

?>
-1
mnz
5 年前
希望這能幫上忙..

在某些伺服器配置中,關聯陣列無法正常運作。以我的情況來說,腳本會停止且不會出現任何錯誤或訊息,`fputcsv` 只是回傳 "false"。

經過一番鑽研和除錯後,我發現關聯陣列在我的本地環境中可以正常運作,但在線上伺服器卻不行。只要移除鍵值就能解決這個問題。

因此,在呼叫 `fputcsv()` 之前先移除鍵值會是比較好的做法。

<?php

// 從陣列中移除鍵值

$csv_fields = array();

foreach(
$associative_array as $value) {
$csv_fields[] = $value;
}

fputcsv( $handler, $csv_fields);

?>
-5
boonerunner at hotmail dot com
19 年前
以下是上述程式碼的改編版本,加入了對欄位內雙引號的支援。(根據 CSV 格式,一個雙引號會被替換成一對雙引號)。

<?php
function fputcsv($filePointer,$dataArray,$delimiter,$enclosure)
{
// 將一行寫入檔案
// $filePointer = 要寫入的檔案資源
// $dataArray = 要寫入的資料
// $delimeter = 欄位分隔符號

// 建構字串
$string = "";

// 沒有前導分隔符號
$writeDelimiter = FALSE;
foreach(
$dataArray as $dataElement)
{
// 將一個雙引號替換成兩個雙引號
$dataElement=str_replace("\"", "\"\"", $dataElement);

// 在每個欄位之前(除了第一個)加入分隔符號
if($writeDelimiter) $string .= $delimiter;

// 用 $enclosure 將每個欄位括起來,並將其加入字串中
$string .= $enclosure . $dataElement . $enclosure;

// 分隔符號用於每次寫入,除了第一次。
$writeDelimiter = TRUE;
}
// foreach($dataArray as $dataElement) 結束

// 附加換行符號
$string .= "\n";

// 將字串寫入檔案
fwrite($filePointer,$string);
}
?>
To Top