phpExcel读入块很慢和内存错误

时间:2013-04-06 14:00:19

标签: phpexcel

我正在尝试读取大约20mb的大型excel文件以导入到mysql中。

我在互联网上搜索并找到了“Chunks reading”解决方案,但是没有工作......或者对我来说很慢,我不知道为什么。

这就是我正在做的事情:

// .....
// into MyReadFilter class.. this is the most important function:
public function readCell($column, $row, $worksheetName = '') {
        //  Only read the rows and columns that were configured
        if (($row == 1) || ($row >= $this->_startRow && $row < $this->_endRow)) {
            if (in_array($column,$this->_columns)) {
                return true;
            }
        }
        return false;
    }
// .....


$filter = new MyReadFilter(1, 22000); 
$chunkSize = 10;

$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objReader->setReadFilter($filter);
$objReader->setReadDataOnly(false); //not sure if this should be true


for ($startRow = 2; $startRow <= 65536; $startRow += $chunkSize) {

  echo "Reading";
  $filterSubset->setRows($startRow, $chunkSize);
  $objPHPExcel = $objReader->load($inputFileName); // this line takes like 40 seconds... for 10 rows?
  echo "chunk done! ";
}

然而,在for中,$ objReader-&gt; load()占用了40秒,事实上,在2次循环之后我遇到了内存错误。

如果我取消设置里面的$ objReader,我可以让它在for ...内运行大约20次(虽然需要10分钟)和...内存错误。

我想知道为什么加载函数似乎读取所有文件,如果即时通讯使用过滤器,过滤器策略似乎解析所有行并返回false为所有不需要的行...是不可能的中止阅读或真正阅读所需的内容?

我尝试了几个FilterClass和代码片段,但结果相同......

1 个答案:

答案 0 :(得分:3)

如果您正在使用过滤器,那么Reader仍在读取整个文件,但只填充过滤器定义的PHPExcel对象单元格;并且Reader仍然需要在每次过滤过程中读取整个文件,这使得它变慢。

由于原始电子表格文件的结构,Reader需要读取整个文件。单元格数据不与单元格格式一起存储,单元格内容也可以单独存储。读者需要将所有这些结合在一起。您不能简单地在满足过滤条件时中止读取器,因为读者无法知道它已经完成...如果您有一个过滤器将负载限制为单元格A1:C3,那么您可以读取B3后中止,因为您不知道文件中是否有单元格B2,或者文件中可能还有与单元格A1相关的注释。在整个文件加载和解析之前,您无法开始过滤。

PHPExcel中的主要内存使用是PHPExcel对象,特别是单元格(通常在32位PHP上大约1k /单元格)....提供减少内存的主要解决方案是单元缓存。这可以(使用SQLite缓存)将单元内存使用量减少到0k / cell,但速度很快。

Reader不会使用比Excel文件(解压缩)本身大小更多的内存,因此通常远不如内存问题;但是,通过从SimpleXML切换到XMLReader,可以解决这个问题(对于基于XML的电子表格格式)。但它取决于正在加载的文件的格式; xls格式文件与xlsx文件非常不同(xlsx将从中受益,xls将不会受益)并且还依赖于开发人员能够找到时间来做到这一点 - 但它是在来年的路线图上,并且工作已经开始了。