使用PHPExcel将XLS文件中的单个工作表转换为CSV - 内存耗尽

时间:2013-03-20 17:13:57

标签: php memory optimization phpexcel

我有一个Excel文件(97-2003),我需要能够通过PHP导入并将文件中的一个工作表转换为CSV。这些是由用户上传的,因此没有手动选择。它需要与PHP。

我目前正在使用PHPExcel,它工作正常,直到我们收到超过33,000行的文件...这导致了致命的PHP错误:Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 97 bytes) in [pathtophpexcel]\PHPExcel\Worksheet.php on line 11231

有没有什么方法可以进一步优化,或者PHPExcel在处理大型工作表时不是正确的选择?我使用的代码相当简单,所以不确定是否可以进一步优化它,但是手指交叉!这是我正在使用的代码:

$reader = PHPExcel_IOFactory::createReader('Excel5');
$reader->setReadDataOnly(true);
$reader->setLoadSheetsOnly('Details');

$excel = $reader->load($filename);

$writer = PHPExcel_IOFactory::createWriter($excel, 'CSV');
$writer->save($filename_fixed);

如果PHPExcel不适合这份工作,我最好用什么?

编辑 - 这是Mark建议后的工作代码

$cacheMethod = PHPExcel_CachedObjectStorageFactory::cache_to_phpTemp;
$cacheSettings = array( 'memoryCacheSize' => '2GB');
PHPExcel_Settings::setCacheStorageMethod($cacheMethod, $cacheSettings);

$reader = PHPExcel_IOFactory::createReader('Excel5');
$reader->setReadDataOnly(true);
$reader->setLoadSheetsOnly('Details');

$excel = $reader->load($filename);

$writer = PHPExcel_IOFactory::createWriter($excel, 'CSV');
$writer->save($filename_fixed);

1 个答案:

答案 0 :(得分:4)

PHPExcel 1.7.3引入了cell caching作为一种机制,可以减少在PHP内存限制内维护大型工作簿的内存使用量。通过序列化单元数据以减小其大小,或者允许将单元数据保存在PHP内存之外,仅在内存中保留单元格的索引,单元格高速缓存提供了一种权衡,从而减少了内存使用量。但是以性能为代价。

默认情况下,单元格缓存会将所有单元格存储在内存中以获得最佳速度;但其他缓存选项包括:

  • 拉链内存
  • 在内存中序列化
  • igbinary在内存中序列化
  • 磁盘上的红色
  • APC
  • 内存缓存
  • WINCACHE
  • phptemp
  • sqlite或sqlite3数据库

它们之间的速度和内存使用情况各不相同,也会因操作平台和其他设置而异,因此您需要确定哪种选择适合您自己的情况;但作为一般准则,内存使用效率越高,性能越低。 SQLite选项是最近添加的,并提供最佳的内存使用,因为即使是"单元索引"并没有在内存中维护,我正在测试一些更改,看看我是否可以提高sqlite的执行速度。

用法在开发人员文档的第4.2.1节中介绍