26

致命错误:第 269 行的 D:\xampplite\htdocs\Scraper\PHPExcel\Reader\Excel2007.php 中允许的内存大小为 134217728 字节已用尽(试图分配 1078799 字节)

即使我只是尝试使用 PHPExcel 打开一个 ~350 KB 的小型 Excel 文件,我的 128M PHP 内存限制也会很快耗尽。

虽然,我可以增加配置中的内存限制,但很高兴看看是否有任何替代方法可以解决这个问题。

4

8 回答 8

64

使用 PHPExcel 时,文件大小不是衡量工作簿文件的好方法。行数和列数(即单元格)更为重要。

PHPExcel 代码本身的占用空间在 10 到 25MB 之间,具体取决于正在访问的组件。

目前,工作簿中的每个单元格平均占用 1k 内存(没有任何缓存)或 1.6k 在 64 位 PHP 上 - 我暂时假设 32 位 PHP - 所以(例如)一个 8000 行的工作表包含 31 列(248,000 个单元格)大约为 242MB。使用单元缓存(例如 php://temp 或 DiskISAM),这可以减少到大约三分之一,因此 8000 行乘 31 列将需要大约 80MB。

有许多选项可帮助您减少内存使用量:

您是否在 PHPExcel 中使用单元缓存?

require_once './Classes/PHPExcel.php';

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

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objPHPExcel = $objReader->load("test.xlsx");

如果您只需要访问工作表中的数据,而不需要访问单元格格式,则可以禁用从工作簿中读取格式信息:

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("test.xlsx");

如果您只需要访问工作簿中的部分工作表,而不是所有工作表,则可以仅加载这些工作表:

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setLoadSheetsOnly( array("Worksheet1", "Worksheet2") );
$objPHPExcel = $objReader->load("test.xlsx");

如果您只想读取工作表中的某些单元格,您可以添加一个过滤器:

class MyReadFilter implements PHPExcel_Reader_IReadFilter
{
    public function readCell($column, $row, $worksheetName = '') {
        // Read title row and rows 20 - 30
        if ($row == 1 || ($row >= 20 && $row <= 30)) {
            return true;
        }

        return false;
    }
}

$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadFilter( new MyReadFilter() );
$objPHPExcel = $objReader->load("test.xlsx");

所有这些技术都可以显着降低内存需求。

于 2010-08-21T21:45:16.757 回答
5

PHPExcel 以内存泄漏而闻名。我建议您使用以下需要PHPExcel 使用的内存的分数

1) 阅读:PHP-Excel-Reader

2)写作:梨电子表格Excel Writer

于 2010-08-21T14:15:25.653 回答
3

仅仅因为数据文件只有 X 字节,并不意味着它使用 X 字节的内存。例如,$_SESSION 数组中只有 4K 的数据在加载时使用了 64K 的内存。它只取决于代码对这些数据做了什么。正确答案是增加ram的数量。

此外,如果这是一个 XLSX 文件,它们是 ZIP 格式的 XML 文档。文本文件的压缩比 1/2 小得多,因此您的 350K XLSX 文件很容易成为 1MB 的 Excel 文件。

于 2010-08-21T12:56:53.557 回答
1

如果您想找出答案,可以使用xhprof。根据此链接,您可以使用它跟踪内存使用情况...

于 2010-08-21T12:38:33.580 回答
1

Xdebug 是 php 的分析器/调试器,可以帮助您跟踪内存使用情况和函数调用以找出问题所在。而且它易于安装,大多数 linux 发行版都在存储库中,“yum install xdebug”,“apt-get install xdebug”。

于 2010-08-21T13:11:41.020 回答
1

您还应该注意的一件事是空单元格。

我有同样的问题,只有 800 行数据,脚本甚至无法读取。修复后的超时和内存不足错误。

@Mark Ba​​ker 关于细胞的一些说法让我开始思考。我注意到我有很多空单元格,并且只将带有数据的单元格复制到新工作簿中,它可以在一秒钟内运行。

希望这可以帮助某人。

于 2012-09-26T17:15:31.957 回答
0
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("test.xlsx");

这么多代码就够了

于 2016-08-05T07:04:17.970 回答
0

这篇文章讨论了如何关闭 PHPExcel 阅读器: 如何在 php-excel-reader 中关闭 excel 文件 如果您同时打开多个 Excel 文件,但实际上并不需要同时打开它们,那么您可以尝试打开并一个一个地关闭(即取消设置)每个文件的阅读器。顺便说一句,为读者使用相同的变量名称就足够了“取消设置”操作。

于 2017-10-24T16:09:19.057 回答