Contents
  1. 1. 前言
  2. 2. 优化数据库查询
  3. 3. 优化导出excel为csv
  4. 4. 编码格式问题
  5. 5. 通过添加文件头解决
  6. 6. 总结

前言

公司承接的一个二次开发伪cms项目(下简称:管理器)中有一个客户需要的导出数据功能。项目在长时间的运营后,数据越来越多,导出一万条数据需要近5分钟,现使用空余时间尝试缩短数据导出时间。

优化数据库查询

管理器中的数据导出功能是先从数据库中获取数据,再使用PHPExcel库生成xls文件。
进行数据库查询优化后(添加索引,使用连表查询,简化sql),数据库查询时间缩短到0.3秒内。再次进行数据导出,发现导出时间依然将近5分钟。

优化导出excel为csv

在分段输出程序运行时间后,确定了是PHPExcel库生成xls文件占用了大量时间。
通过网上搜索后发现php使用PHPExcel库生成xls文件慢是通病,很多人建议直接拼接字符串导出csv以代替使用PHPExcel库。
将导出格式改为csv后速度的确是大大提高,不到1秒数据导出就完成了。

编码格式问题

本地测试通过后,提交升级的第一天,客户就发现问题了,在我们公司内打开没问题的csv。到他们电脑上打开,所有汉字均变成问号?,和客户沟通后发现,原来是他们的office的默认语言是英文。但是由于客户公司内部规定,不能随意更改。

通过添加文件头解决

在把本地电脑里excel的语言也设置为默认英语后,问题能够重现了。
不使用iconv对汉字内容转码的情况下,导出数据csv默认的编码方式是UTF-8,在经过多方测试后,发现只要把csv文件的编码方式设置为UTF-8-BOM,也就是为UTF-8多加了一个文件头,两个文件在十六进制编码下进行对比差异如下。
文件编码方式UTF-8
文件编码方式UTF-8-BOM
两下对比,多出的文件头是ef bb bf,这是Unicode签名BOM(Byte Order Mark),网上有很多关于BOM的介绍,这里不细究。
于是在程序输出csv时,在文件的开头处加上这个BOM,英文版excel就能正确读取带有汉字的csv了。

1
2
3
4
$fp = fopen('php://output', 'a');
//设置文件头 ef bb bf
fputs($fp,chr(239).chr(187).chr(191));
fputs($fp,$content);

总结

一些外企内部有规定必须使用英文版操作系统甚至office的默认语言也必须是英文,这就导致了没有内置编码方式设置的csv在非汉语环境下打开产生汉字变问号的问题。
在制作导出数据功能时,假如需要导出带汉字的csv文件,最好加上文件头,这样无论excel的默认语言是什么,只要系统内置了汉语文字编码,就能够正常显示汉字。

Contents
  1. 1. 前言
  2. 2. 优化数据库查询
  3. 3. 优化导出excel为csv
  4. 4. 编码格式问题
  5. 5. 通过添加文件头解决
  6. 6. 总结