PHP 导出CSV文件部分行错位
使用PHP fputcsv 或者 fwrite 方法导出大概1万7千条数据,出现大概6条到10条左右的数据错位情况。
代码:
public static function createCsv($data, $header = [], $filename = '')
{
// 参数判断
$data = is_object($data) ? $data->toArray() : $data;
$header = is_array($header) ? $header : [];
$filename = (1 > strlen(trim($filename))) ? 'csv-' : trim($filename);
if (empty($data)) {
return false;
}
// 文件名/目录
$filename = $filename . date("YmdHis", time()) . rand(1000, 9999) . ".csv";
$dir = \Env::get('runtime_path') . '/export/';
if (!is_dir($dir) && !mkdir($dir)) {
return false;
}
// 打开文件指针资源
$handle = fopen($dir . $filename, 'w+');
if (!$handle) {
return false;
}
// 写入文件header头
if (!empty($header)) {
$res = fputcsv($handle, $header);
if (!$res) {
return false;
}
}
// 判断header是索引数组还是关联数组
$is_assoc = array_keys($header) !== range(0, count($header) - 1);
// 写入文件内容
$frequency = 0; // 频率
$limit = 100000;
foreach ($data as $datum) {
$frequency++;
if ($limit == $frequency) {
// 刷新输出buffer
ob_flush();
flush();
$frequency = 0;
}
// 如果是关联数组,则获取内容中和头部key相对应的值
if ($is_assoc) {
$csv = "";
foreach(array_keys($header) as $item) {
$val = str_replace('"', '""', "\t" . $datum[$item]);
$csv .= '"' . $val . '",';
}
$csv = substr($csv, 0, -1);
$csv .= "\n";
$res = @fwrite($handle, $csv);
} else {
$res = fputcsv($handle, $datum);
}
if (!$res) {
return false;
}
}
// 关闭指针资源
fclose($handle);
return \Url::build('erp/Common/export', 'file=' . $filename);
}
出现的情况:
同样的数据筛选之后发现也只有这一条出现问题
源码:
发现该行的逗号分隔符去到双引号里了,请问出现这种问题的原因是什么。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
经过一个下午的折腾,上周五还是发现出现该异常情况的原因。概括来说还是中文转编码的问题,即utf-8转gbk出现的小部分行缺少空格或者双引号的问题。
出现问题的原因:
在进行导出的过程中,接收其他程序传过来的数组参数,均为utf-8编码,我这边在调用fwrite或者fputcvs写入文件的过程中并没有进行 iconv("UTF-8", "GB2312//IGNORE", $header),而是将文件保存在了 export目录下,然后由vuejs做的后台调用位于同application下的一个共用类的 export方法,该方法是这样的:
问题就出在 echo iconv("UTF-8", "GB2312//IGNORE", $contents); 这句代码上面,这里看到是对传入的整个文件进行转编码的,这里未进行测试到底多少行的数据会出现缺少逗号引号的问题。
最终的解决思路是,把共用类中对整个文件的转编码放到写入方法中,逐条转编码就解决了该问题。
更改后的代码:
调用步骤:
先调用createCsv生成文件,再调用export下载。
———————————————————————分割线——————————————————————
另外一种解决思路:
csv文件直接存储 UTF-8 编码:
即不需要进行 iconv 转编码,这样会有个小问题就是MacOS中的Excel无法自动识utf-8编码,中文会出现乱码的情况。
原因:
根据知乎查到的答案,原来是这里未遵循微软的bom协议。原因找到了,解决方案就能出了。
解决方法:
fopen 方法下写入bom头,这里简单写一下步骤
另外再补充一下 Bom 简介
该内容来自 http://blog.csdn.net/chaozhi_... 这篇博客