大读时的内存 Excel 2007 (.xlsx)
Memory while reading large Excel 2007 (.xlsx)
我正在使用我以前用过很多次的 PHPExcel。我现在遇到的问题是读取 Excel2007 文件(.xlsx - 格式)时。我正在做的只是简单地循环 .xlsx
文件并通过 row/column 创建一个数组,然后 print_r()
-ing 在读取操作之后的结果以确保之前的数据输出是好的将其导入 MySQL 数据库。
现在读取 Excel2007 .xlsx
文件 (6MB) 时输出失败,但有趣的是如果我将文件保存为旧格式 .xls
(1992-2004 - Excel5) 文件变大(16MB)但输出正确。这让我认为最初这不是内存问题,因为较旧的较大 .xls
文件 (16MB) 运行 没有问题,几乎是 .xlsx
文件 (6MB) 大小的 3 倍.
出于测试目的,我随后复制了 .xlsx
(6MB) 文件中的 30,000 行中的 25 行,并创建了一个新的 Excel2007 .xlsx
和 运行 针对较小的 25 行导入数据集并正确输出。这让我认为这是一个内存问题,但具体与 .xlsx
格式有关...
我运行在 Amazon Web Services 上安装服务器并拥有 C4.Xlarge(16 核,30GB RAM)所以我应该有足够的资源来 运行 这个操作.
问题:为什么我的输出在读取较小的 .xlsx
文件与较大的 .xls
文件时失败,但随后读取较小的 .xlsx
(25行)文件?
//PHP函数
function parse_xls($file){
ini_set('memory_limit','-1');
$type = PHPExcel_IOFactory::identify($file);
$reader = PHPExcel_IOFactory::createReader($type);
$reader->setReadDataOnly(true);
$xls = $reader->load($file);
$sheet = $xls->getActiveSheet();
$highestRow = $sheet->getHighestRow();
$highestColumn = $sheet->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
for($row=2; $row <= ($highestRow+2); $row++){
$import[$row] = [];
for($col=0; $col < $highestColumnIndex; $col++){
$result = $sheet->getCellByColumnAndRow($col, $row)->getValue();
array_push($import[$row],$result);
}
}
print_r($import);
die();
}
对于大文件我使用 chunkReadFilter
$iChunkSize=1000;
for($iStartRow = $row_start; $iStartRow <= $totalRows; $iStartRow += $iChunkSize) {
$objReader = $oExcel->SetCreateReader();
$oChunkFilter = new chunkReadFilter();
$objReader->setReadFilter($oChunkFilter);
$oChunkFilter->setRows($iStartRow,$iChunkSize);
$objReader->setReadFilter($oChunkFilter);
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($files['path']);
$objPHPExcel->setActiveSheetIndex($iList);
$sFromCell = 'A'.$iStartRow;
$aData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,false,$sFromCell);
// free memory
unset($objPHPExcel);
unset($objReader);
unset($oChunkFilter);
// parse data
foreach ($aData as $sKey => $aValue) {
...
}
// real data rows
if (count($aData) < $iChunkSize) {
unset($aData);
break;
}
unset($aData);
}
我正在使用我以前用过很多次的 PHPExcel。我现在遇到的问题是读取 Excel2007 文件(.xlsx - 格式)时。我正在做的只是简单地循环 .xlsx
文件并通过 row/column 创建一个数组,然后 print_r()
-ing 在读取操作之后的结果以确保之前的数据输出是好的将其导入 MySQL 数据库。
现在读取 Excel2007 .xlsx
文件 (6MB) 时输出失败,但有趣的是如果我将文件保存为旧格式 .xls
(1992-2004 - Excel5) 文件变大(16MB)但输出正确。这让我认为最初这不是内存问题,因为较旧的较大 .xls
文件 (16MB) 运行 没有问题,几乎是 .xlsx
文件 (6MB) 大小的 3 倍.
出于测试目的,我随后复制了 .xlsx
(6MB) 文件中的 30,000 行中的 25 行,并创建了一个新的 Excel2007 .xlsx
和 运行 针对较小的 25 行导入数据集并正确输出。这让我认为这是一个内存问题,但具体与 .xlsx
格式有关...
我运行在 Amazon Web Services 上安装服务器并拥有 C4.Xlarge(16 核,30GB RAM)所以我应该有足够的资源来 运行 这个操作.
问题:为什么我的输出在读取较小的 .xlsx
文件与较大的 .xls
文件时失败,但随后读取较小的 .xlsx
(25行)文件?
//PHP函数
function parse_xls($file){
ini_set('memory_limit','-1');
$type = PHPExcel_IOFactory::identify($file);
$reader = PHPExcel_IOFactory::createReader($type);
$reader->setReadDataOnly(true);
$xls = $reader->load($file);
$sheet = $xls->getActiveSheet();
$highestRow = $sheet->getHighestRow();
$highestColumn = $sheet->getHighestColumn();
$highestColumnIndex = PHPExcel_Cell::columnIndexFromString($highestColumn);
for($row=2; $row <= ($highestRow+2); $row++){
$import[$row] = [];
for($col=0; $col < $highestColumnIndex; $col++){
$result = $sheet->getCellByColumnAndRow($col, $row)->getValue();
array_push($import[$row],$result);
}
}
print_r($import);
die();
}
对于大文件我使用 chunkReadFilter
$iChunkSize=1000;
for($iStartRow = $row_start; $iStartRow <= $totalRows; $iStartRow += $iChunkSize) {
$objReader = $oExcel->SetCreateReader();
$oChunkFilter = new chunkReadFilter();
$objReader->setReadFilter($oChunkFilter);
$oChunkFilter->setRows($iStartRow,$iChunkSize);
$objReader->setReadFilter($oChunkFilter);
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($files['path']);
$objPHPExcel->setActiveSheetIndex($iList);
$sFromCell = 'A'.$iStartRow;
$aData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,false,$sFromCell);
// free memory
unset($objPHPExcel);
unset($objReader);
unset($oChunkFilter);
// parse data
foreach ($aData as $sKey => $aValue) {
...
}
// real data rows
if (count($aData) < $iChunkSize) {
unset($aData);
break;
}
unset($aData);
}