我的内存问题是xlsx文件大约95.500行和28列。 为了处理这样大的文件(超过10 MB xlsx),我写了下面的代码,但是当我执行代码并调用load方法时,即使只有一行读取,我也会收到内存耗尽错误! (我只分配了128Mb到php解释器)
请考虑:
目前我尝试只读取一行并收到有关内存耗尽的错误(请参阅$ chunkFilter-> setRows(1,1);)
解决了读取第一行的问题后,我需要读取所有其他行以在数据库表中加载内容
如果您认为还有其他库或解决方案,请考虑我更喜欢PHP作为语言,因为它是此应用程序使用的主要语言但我可以接受任何其他语言的解决方案(如go)
请不要简单地建议增加php进程的内存。我知道这是可能的,但是这个代码在VPS共享服务器上运行,最大RAM只有512Mb,我需要尽可能地降低内存使用率
有解决方案吗?请找到我使用的以下代码:
/** Define a Read Filter class implementing PHPExcel_Reader_IReadFilter to read file in "chunks" */
class chunkReadFilter implements PHPExcel_Reader_IReadFilter {
private $_startRow = 0;
private $_endRow = 0;
/** Set the list of rows that we want to read */
public function setRows($startRow, $chunkSize) {
$this->_startRow = $startRow;
$this->_endRow = $startRow + $chunkSize;
}
public function readCell($column, $row, $worksheetName = '') {
// Only read the heading row, and the rows that are configured in $this->_startRow and $this->_endRow
if (($row == 1) || ($row >= $this->_startRow && $row < $this->_endRow)) {
return true;
}
return false;
}
}
function loadXLSFile($inputFile){
// Initiate cache
$cacheMethod = PHPExcel_CachedObjectStorageFactory:: cache_to_sqlite3;
if (!PHPExcel_Settings::setCacheStorageMethod($cacheMethod)) {
echo date('H:i:s'), " Unable to set Cell Caching using ", $cacheMethod,
" method, reverting to memory", EOL;
}
$inputFileType = PHPExcel_IOFactory::identify($inputFile);
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$chunkFilter = new chunkReadFilter();
// Tell the Read Filter, the limits on which rows we want to read this iteration
$chunkFilter->setRows(1,1);
// Tell the Reader that we want to use the Read Filter that we've Instantiated
$objReader->setReadFilter($chunkFilter);
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($inputFile);
}
更新
根据pamelus
的要求返回错误PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 112 bytes) in /vendor/phpoffice/phpexcel/Classes/PHPExcel/Reader/Excel2007.php on line 471
PHP Stack trace:
PHP 1. {main}() dataimport.php:0
PHP 2. loadFileToDb($inputFile = *uninitialized*, $tabletoupdate = *uninitialized*) dataimport.php:373
PHP 3. PHPExcel_Reader_Excel2007->load($pFilename = *uninitialized*) dataimport.php:231
答案 0 :(得分:1)
鉴于您的内存限制很低,我可以建议您替代PHPExcel,以便一劳永逸地解决您的问题:Spout。它只需要10MB的内存,所以你应该很好!
您的loadXLSXFile()
功能将变为:
use Box\Spout\Reader\ReaderFactory;
use Box\Spout\Common\Type;
function loadXLSFile($inputFile) {
$reader = ReaderFactory::create(Type::XLSX);
$reader->open($inputFile);
foreach ($reader->getSheetIterator() as $sheet) {
foreach ($sheet->getRowIterator() as $row) {
// $row is the first row of the sheet. Do something with it
break; // you won't read any other rows
}
break; // if you only want to read the first sheet
}
$reader->close();
}
就这么简单!无需缓存,过滤器和其他优化:)