Spout简介
使用phpExcel在读取体积较大的excel文件时,会提示Fatal error: Allowed memory size of
的错误,提示内存不够。可以使用Spout来解决。
Spout 是一个 PHP 库,用于以快速且可扩展的方式读取和写入电子表格文件(CSV、XLSX 和 ODS)。它能够处理非常大的文件,同时保持非常低的内存使用率(小于 3MB)。
官方网站:
https://opensource.box.com/spout/
github地址:
https://github.com/box/spout
安装方法
通过composer
或手动引入。
通过composer:
composer require box/spout
手动引入:
require_once '[PATH/TO]/src/Spout/Autoloader/autoload.php';
DEMO
use Box\Spout\Reader\Common\Creator\ReaderEntityFactory;
$filePath = '/path/to/file.xlsx';
$reader = ReaderEntityFactory::createReaderFromFile($filePath);
$reader->open($filePath);
foreach ($reader->getSheetIterator() as $sheet) {
//只取第一个sheet
if($sheet->getIndex()>0) continue;
foreach ($sheet->getRowIterator() as $row) {
// do stuff with the row
$cells = $row->getCells();
$tmp = [];
foreach ($cells as $k=>$cell){
$value = $cell->getValue();
if(strlen($value)>0) $tmp[$k+1] = $value;
}
var_dump($tmp);die;
}
}
$reader->close();
另一种办法
将xlsx文件转为csv文件,使用PHP的原生函数如fgetcsv()
来读取,这通常是处理非常大的数据集的最快方法。使用 fgetcsv()
函数是读取大型 CSV 文件的一个非常高效的方法,因为它允许你逐行处理文件,而不需要一次性将整个文件加载到内存中。
以下是一个使用 fgetcsv()
读取大型 CSV 文件的例子:
<?php
function readLargeCsv($filename, $delimiter = ',') {
// 检查文件是否存在
if (!file_exists($filename) || !is_readable($filename)) {
return false;
}
// 打开文件
$handle = fopen($filename, 'r');
if ($handle === false) {
return false;
}
// 设置一个计数器来跟踪处理的行数
$row = 0;
// 读取文件头(假设第一行是列名)
$header = fgetcsv($handle, 0, $delimiter);
if ($header === false) {
fclose($handle);
return false;
}
$row++;
// 逐行读取文件内容
while (($data = fgetcsv($handle, 0, $delimiter)) !== false) {
$row++;
// 使用 $header 和 $data 创建关联数组
$rowData = array_combine($header, $data);
// 在这里处理每一行的数据
// 例如,你可以将数据插入数据库,或者进行一些计算
processRow($rowData, $row);
// 可选:每处理 1000 行后,输出一个进度指示
if ($row % 1000 === 0) {
echo "Processed $row rows\n";
// 可选:刷新输出缓冲
flush();
ob_flush();
}
}
// 关闭文件
fclose($handle);
return $row; // 返回处理的总行数
}
function processRow($rowData, $rowNumber) {
// 在这里处理每一行的数据
// 这只是一个示例,你需要根据你的具体需求来实现这个函数
echo "Processing row $rowNumber: " . json_encode($rowData) . "\n";
}
// 使用示例
$filename = 'path/to/your/large_file.csv';
$totalRows = readLargeCsv($filename);
if ($totalRows === false) {
echo "An error occurred while reading the file.\n";
} else {
echo "Total rows processed: $totalRows\n";
}