当我使用fputcsv向打开的文件句柄写出一行时,PHP 会在它认为需要它的任何列中添加一个封闭字符,但会留下其他列而没有封闭字符。
例如,您可能会得到这样的一行
11,"Bob ",Jenkins,"200 main st. USA ",etc
除了在每个字段的末尾附加一个虚假的空间之外,有没有办法强制 fputcsv 始终将列与附件(默认为“)字符括起来?
不,fputcsv() 仅在以下条件下包含该字段
/* enclose a field that contains a delimiter, an enclosure character, or a newline */
if (FPUTCSV_FLD_CHK(delimiter) ||
FPUTCSV_FLD_CHK(enclosure) ||
FPUTCSV_FLD_CHK(escape_char) ||
FPUTCSV_FLD_CHK('\n') ||
FPUTCSV_FLD_CHK('\r') ||
FPUTCSV_FLD_CHK('\t') ||
FPUTCSV_FLD_CHK(' ')
)
没有“始终包含”选项。
对这个解决方案不满意,但这是我所做和工作的。这个想法是在 fputcsv 上设置一个空字符作为附件字符,并在数组的每个元素上添加一些引号。
function encodeFunc($value) {
return "\"$value\"";
}
fputcsv($handler, array_map(encodeFunc, $array), ',', chr(0));
基于Martin的回答,如果您想避免插入任何不源自源数组(Chr(127)
、Chr(0)
等)的字符,您可以将 fputcsv() 行替换为以下内容:
fputs($fp, implode(",", array_map("encodeFunc", $row))."\r\n");
当然,fputs() 比 fputcsv() 慢,但它的输出更清晰。完整的代码如下:
/***
* @param $value array
* @return string array values enclosed in quotes every time.
*/
function encodeFunc($value) {
///remove any ESCAPED double quotes within string.
$value = str_replace('\\"','"',$value);
//then force escape these same double quotes And Any UNESCAPED Ones.
$value = str_replace('"','\"',$value);
//force wrap value in quotes and return
return '"'.$value.'"';
}
$fp = fopen("filename.csv", 'w');
foreach($table as $row){
fputs($fp, implode(",", array_map("encodeFunc", $row))."\r\n");
}
fclose($fp);
经过大量的折腾和一些有些乏味的字符检查后,我得到了Diego和Mahn的上述引用代码的一个版本,它将正确地去除封装并在fputcsv
. 然后将文件输出到浏览器下载。
我还有一个次要问题,即无法确定双引号总是/从未逃脱。
特别是在使用 Diego 引用的 php://input 流直接输出到浏览器时。Chr(127)
是一个空格字符,所以 CSV 文件比其他文件有更多的空格,但我相信这回避了chr(0)
UTF-8 中 NULL 字符的问题。
/***
* @param $value array
* @return string array values enclosed in quotes every time.
*/
function encodeFunc($value) {
///remove any ESCAPED double quotes within string.
$value = str_replace('\\"','"',$value);
//then force escape these same double quotes And Any UNESCAPED Ones.
$value = str_replace('"','\"',$value);
//force wrap value in quotes and return
return '"'.$value.'"';
}
$result = $array_Set_Of_DataBase_Results;
$fp = fopen('php://output', 'w');
if ($fp && $result) {
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="export-'.date("d-m-Y").'.csv"');
foreach($result as $row) {
fputcsv($fp, array_map("encodeFunc", $row), ',', chr(127));
}
unset($result,$row);
die;
}
我希望这对某些人有用。
如果您可以接受,“快速而肮脏”的解决方案是在所有字段的末尾添加 ' ':
function addspace($v) {
return $v.' ';
}
fputcsv($handle, array_map('addspace', $fields));
PS:为什么它有效?见沃尔克回答;)