您好,欢迎访问一九零五行业门户网

如何用box/spout解析大型Excel表格

php解析excel有个比较有名的库是phpoffice/phpexcel。在实际使用的过程中,遇到上万行的excel时,phpexcel的内存使用量会飙升。今天我来介绍另一个高效解析excel的php库box/spout。
看官方介绍是:read and write spreadsheet files in a fast and scalable way,可见这个库在解析excel时,excel文件的大小不会太影响内存的使用量。可以说是phpexcel一种替代方案。
由于box/spout库的github主页上的文档链接已经挂了,这里简单写了一个xlsx文件转化成csv的例子:
include 'vendor/autoload.php';use box\spout\reader\readerfactory;use box\spout\common\type;$t = time();$reader = readerfactory::create(type::xlsx);//如果注释掉,单元格内的日期类型将会是datetime,不注释的话spout自动帮你将日期转化成string//$reader->setshouldformatdates(true);$reader->open('./test.xlsx');$iterator = $reader->getsheetiterator();$iterator->rewind();$sheet1 = $iterator->current();$rowiter = $sheet1->getrowiterator();foreach ($rowiter as $row) { $d = ''; foreach ($row as $col) { echo $d; if ($col instanceof datetime) { echo $col->format('y-m-d'); } else { echo $col; } $d = "\t"; } echo php_eol;}$reader->close();
使用方法还是很简洁明了的。
使用内存缓存string字典前面说到box/spout在解析时消耗的内存大小,不受excel文件大小的影响,这是如何做到的呢?
这里简单科普一下:xlsx文件格式是符合一项标准的,这项标准叫做ooxml(https://zh.wikipedia.org/zh-cn/office_open_xml)。xlsx实际上就是一个zip包,可以解压缩出来看看其中的内容。
xlsx表格中,如果单元格的内容是一串字符串时,实际保存的时候只保存一个stringid,字符串真正的内容保存在一个string字典中。
在读取xlsx文件时,如果单元格是字符串,spout就要去查询string字典。spout有两种查询方法,一是每次从文件里读取字典的一部分查询,二是把整个字典加载到内存里查询。
显然把string字典整个加载到内存里,查询速度最快。但spout过于保守,很多情况下都是采用第一种查询方式。所以稍微修改下spout的代码,让spout尽量把字典全部加载到内存:
# spout/reader/xlsx/helper/sharedstringscaching/cachingstrategyfactory.phpclass cachingstrategyfactory { .... const max_num_strings_per_temp_file = 10000; // 改成50000 ....}
试验一个1.3w行、28列、2.8mb大小的excel转化成csv,做个对比:
方式耗时占用内存
字典不加载到内存 185 s 1.3 mb
字典加载到内存 43 s 9.4 mb
可见处理时间相差还是挺大的。
推荐学习:php视频教程
以上就是如何用box/spout解析大型excel表格的详细内容。
其它类似信息

推荐信息