如果您需要將 CSV 檔案直接傳送到瀏覽器,而無需寫入外部檔案,您可以開啟輸出並在其上使用 fputcsv。
<?php
$out = fopen('php://output', 'w');
fputcsv($out, array('this','is some', 'csv "stuff", you know.'));
fclose($out);
?>
(PHP 5 >= 5.1.0、PHP 7、PHP 8)
fputcsv — 將行格式化為 CSV 並寫入檔案指標
$stream
,$fields
,$separator
= ",",$enclosure
= "\"",$escape
= "\\",$eol
= "\n"
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
。
如果 separator
或 enclosure
的長度不是一個位元組,則會拋出 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"""
如果您需要將 CSV 檔案直接傳送到瀏覽器,而無需寫入外部檔案,您可以開啟輸出並在其上使用 fputcsv。
<?php
$out = fopen('php://output', 'w');
fputcsv($out, array('this','is some', 'csv "stuff", you know.'));
fclose($out);
?>
如果您需要將輸出儲存到變數中(例如,在框架內使用),您可以寫入暫時的記憶體封裝器並檢索其內容
<?php
// 輸出最多 5MB 的內容會保留在記憶體中,如果超過這個大小,則會自動寫入臨時檔案
$csv = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
fputcsv($csv, array('blah','blah'));
rewind($csv);
// 將所有內容放入變數中
$output = stream_get_contents($csv);
?>
有時候將 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);
}
?>
如果您想要製作 Excel 可用的 UTF-8 檔案,請使用這個方法
$fp = fopen($filename, 'w');
//新增 BOM 以修正 Excel 中的 UTF-8 問題
fputs($fp, $bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ));
請注意,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)
- 空白
我希望這能為您省下我花費一個小時才弄清楚這個行為的時間。
為了與標準 (RFC-4180) CSV 檔案達到最大的相容性,請記得停用專屬的跳脫機制。也就是說,將可選的第五個參數設定為 "" (空字串)。
在所有這些情況下,您都需要一個具有自訂記錄分隔功能的無錯誤 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);
}
?>
以 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' 相同,因為在這種情況下 \ 只會用於跳脫,但如果您使用雙引號,則可以正常運作。
以下是如何在將陣列轉換為 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, '|');
}
}
公用函數,用於將 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);
?>
我建立了一個函數,用於快速產生可與 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;
}
?>
好的,在試用了一段時間後,我確信以下替代函數在所有情況下都能正常運作,包括原生 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'
*/
?>
我從 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);
}
}
?>
若要產生符合 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";
如果您不想將字串括起來(因為您自己管理或您的內容已經被括起來了?),請注意您不能將空括號傳遞給 fputcsv。該函數需要該參數有一個字元。chr(0) 效果很好
fputcsv($handle, $fields, ",", chr(0));
[由 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
一般來說,我發現自己想要取得的是字串結果,而不是寫入檔案。特別是,我想要產生一個 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
我們有一個函式可以寫入單行 CSV。我注意到啟用 auto_detect_line_endings 後,fputcsv 不會在檔案末尾寫入換行符。
啟用 auto_detect_line_endings 後,會變更 fputcsv 的行為以包含換行符。
關於 Excel 和 UTF-16LE 編碼
為了完全相容於 Excel(變音符號、西里爾字母、中文字母等),需要將 .csv 編碼為 UTF-16LE,使用 Tab 字元 (\t) 作為分隔符,並在檔案開頭包含 UTF-16LE BOM。
然而,這無法透過簡單地編碼 putcsv 的輸入來完成,因為分隔符和封閉符號仍將以預設編碼寫入,並且 fputcsv 不會接受 UTF-16 編碼的分隔符/封閉符號。
簡單的解決方案是使用逸出等功能來自行實作 fputcsv,或在事後編碼產生的 .csv 檔案。
當您使用 fputcsv 輸出 csv 時,如果包含任何中文字符,您可能會得到亂碼。然後您需要正確設定編碼。
fprintf($fp, chr(0xEF).chr(0xBB).chr(0xBF)); // 只需加入這一行
fputcsv($fp, ...);
受到 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);
}
我發現 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);
}
}
?>
將 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 '';
}
}
?>
希望這能幫上忙..
在某些伺服器配置中,關聯陣列無法正常運作。以我的情況來說,腳本會停止且不會出現任何錯誤或訊息,`fputcsv` 只是回傳 "false"。
經過一番鑽研和除錯後,我發現關聯陣列在我的本地環境中可以正常運作,但在線上伺服器卻不行。只要移除鍵值就能解決這個問題。
因此,在呼叫 `fputcsv()` 之前先移除鍵值會是比較好的做法。
<?php
// 從陣列中移除鍵值
$csv_fields = array();
foreach($associative_array as $value) {
$csv_fields[] = $value;
}
fputcsv( $handler, $csv_fields);
?>
以下是上述程式碼的改編版本,加入了對欄位內雙引號的支援。(根據 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);
}
?>