在百度查php导出excel资料的时候,无意间发现,还有php导出csv文件的功能。
他们二者没有什么区别。具体看需求。
但是要操作的文件特别大的时候,推荐使用csv。
导出csv的时候,需要用到一些php原生函数。我百度了一下基本用法。附上链接
Fgetcsv()
参考:http://www.w3school.com.cn/php/func_filesystem_fgetcsv.asp
复制代码
Fputcsv()
参考:http://www.w3school.com.cn/php/func_filesystem_fputcsv.asp
复制代码
Fopen()
参考:http://www.w3school.com.cn/php/func_filesystem_fputcsv.asp
复制代码
Iconv()
参考:http://php.net/manual/fr/function.iconv.php
复制代码
先是导出:两种方法:
使用 header
我这里使用的是thinkphp3.2框架
/**
* 导出csv
*/
public function putCsv(){
$tableheader = array('姓名', '性别', '年龄', '学院', '班级');
$tablelength = count($tableheader);
/*表格数据*/
$data = M()->query("SELECT id,username,logtime,gid,ip FROM admin");
/*输入到CSV文件 解决乱码问题*/
$html = "xEFxBBxBF";
/*输出表头*/
foreach ($tableheader as $value) {
$html .= $value . " ,";
}
$html .= "
";
/*输出内容*/
foreach ($data as $value) {
for ($i = 0; $i < $tablelength; $i++) {
$html .= $value[$i] . " ,";
}
$html .= $value['createtime'] . " ,";
$html .= "
";
}
/*输出CSV文件*/
header("Content-type:text/csv");
header("Content-Disposition:attachment; filename=全部数据.csv");
echo $html;
exit();
}
复制代码
使用上边那些函数:
/**
* 重写fputcsv方法,添加转码功能
* @param $handle
* @param array $fields
* @param string $delimiter
* @param string $enclosure
* @param string $escape_char
*/
function fputcsv2($handle, array $fields, $delimiter = ",", $enclosure = '"', $escape_char = "\") {
foreach ($fields as $k => $v) {
$fields[$k] = iconv("UTF-8", "GB2312//IGNORE", $v); // 这里将UTF-8转为GB2312编码
}
fputcsv($handle, $fields, $delimiter, $enclosure, $escape_char);
}
/**
* 导出csv
*/
public function csv()
{
set_time_limit(0);
ini_set('memory_limit', '128M');//设置文件最大限制
$fileName = date('YmdHis', time());//文件名
// 设置头部
header('Content-Encoding: UTF-8');
header("Content-type:application/vnd.ms-excel;charset=UTF-8");
header('Content-Disposition: attachment;filename="' . $fileName . '.csv"');
//注意,数据量在大的情况下。比如导出几十万到几百万,
//会出现504 Gateway Time-out,请修改php.ini的max_execution_time参数
//打开php标准输出流以写入追加的方式打开
$fp = fopen('php://output', 'a');
//设置标题
$title = array('id', '编号', '姓名', '年龄');
//注意这里是小写id,否则ID命名打开会提示Excel 已经检测到"xxx.xsl"是SYLK文件,但是不能将其加载: CSV 文或者XLS文件的前两个字符是大写字母"I","D"时,会发生此问题。
foreach ($title as $key => $item){
$title[$key] = iconv("UTF-8", "GB2312//IGNORE", $item);
}
fputcsv2($fp, $title);
// 导出百万级别数据时才需要用到for循环
//用fputcsv从数据库中导出1百万的数据,比如我们每次取1万条数据,分100步来执行
//一次性读取1万条数据,也可以把$nums调小,$step相应增大。
//$step = 100;
//$nums = 10000;
// for ($s = 1; $s <= $step; $s++) {
// $start = ($s - 1) * $nums;
$result = M()->query("SELECT id,username,logtime,gid FROM admin");
foreach($result as $key=>$row){
foreach ($row as $key => $item){
$row[$key] = iconv("UTF-8", "GBK", $item); //这里必须转码,不然会乱码
}
fputcsv($fp, $row);
}
//ob_flush(); //每1万条数据就刷新缓冲区
//flush();
// }
}
复制代码
使用 header 导出这个就没有可说的了。
重点说下下边这个。
上边我注释掉的所有代码都是有用的,当你导出的数据量特别大的时候。
上边的测试是以百万级别的。
具体的,上边都有注释。看不明白的,请在下方留言。
下边是导入:
/**
* 导入csv
*/
public function incsv()
{
$data = $this->csv_get_lines('./uploads/csv/20181221090925.csv', 10, 0);
echo "<pre>";
var_dump($data);
// 加下来是将返回数组的数据插入数据库。这部分不做测试。
}
/**
* csv_get_lines 读取CSV文件中的某几行数据
* @param $csvfile csv文件路径
* @param $lines 读取行数
* @param $offset 起始行数
* @return array
* */
public function csv_get_lines($csvfile, $lines, $offset = 0)
{
if(!$fp = fopen($csvfile, 'r')) {
return false;
}
$i = $j = 0;
while (false !== ($line = fgets($fp))) {
if($i++ < $offset) {
continue;
}
break;
}
$data = array();
while(($j++ < $lines) && !feof($fp)) {
$info = fgetcsv($fp);
foreach ($info as $key => $item){
$info[$key] = iconv("GBK", "UTF-8", $item); //这里必须转码,不然会乱码
}
$data[] = $info;
}
fclose($fp);
return $data;
}
复制代码
导入这个着重说一下参数。
$lines 读取行数
$offset 起始行数
也就是说,从哪开始读取,读取到哪里你是可以控制的,这样方便了大文件的导出。
百万级的文件,分一百次导入,一次导入一万条。我觉得要比一次直接导入一百万条数据要好。
有好的建议,请在下方输入评论
欢迎访问个人博客 guanchao.site
欢迎访问我的小程序:打开微信->发现->小程序->搜索“时间里的”