- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我不明白。 XSLX 表大约有 3MB 大,但即使是 1024MB 的 RAM 也不足以让 PHPExcel 将其加载到内存中吗?
我这里可能做错了什么:
function ReadXlsxTableIntoArray($theFilePath)
{
require_once('PHPExcel/Classes/PHPExcel.php');
$inputFileType = 'Excel2007';
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($theFilePath);
$rowIterator = $objPHPExcel->getActiveSheet()->getRowIterator();
$arrayData = $arrayOriginalColumnNames = $arrayColumnNames = array();
foreach($rowIterator as $row){
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(false); // Loop all cells, even if it is not set
if(1 == $row->getRowIndex ()) {
foreach ($cellIterator as $cell) {
$value = $cell->getCalculatedValue();
$arrayOriginalColumnNames[] = $value;
// let's remove the diacritique
$value = iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $value);
// and white spaces
$valueExploded = explode(' ', $value);
$value = '';
// capitalize the first letter of each word
foreach ($valueExploded as $word) {
$value .= ucfirst($word);
}
$arrayColumnNames[] = $value;
}
continue;
} else {
$rowIndex = $row->getRowIndex();
reset($arrayColumnNames);
foreach ($cellIterator as $cell) {
$arrayData[$rowIndex][current($arrayColumnNames)] = $cell->getCalculatedValue();
next($arrayColumnNames);
}
}
}
return array($arrayOriginalColumnNames, $arrayColumnNames, $arrayData);
}
上述函数将数据从 excel 表读取到数组。
有什么建议吗?
起初,我允许 PHP 使用 256MB 的 RAM。这还不够。然后我将数量加倍,然后也尝试了 1024MB。它仍然因此错误而耗尽内存:
Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 50331648 bytes) in D:\data\o\WebLibThirdParty\src\PHPExcel\Classes\PHPExcel\Reader\Excel2007.php on line 688
Fatal error (shutdown): Allowed memory size of 1073741824 bytes exhausted (tried to allocate 50331648 bytes) in D:\data\o\WebLibThirdParty\src\PHPExcel\Classes\PHPExcel\Reader\Excel2007.php on line 688
最佳答案
PHPExcel 论坛上有很多关于 PHPExcel 内存使用的文章;因此,阅读之前的一些讨论可能会给您一些想法。 PHPExcel 保存电子表格的“内存中”表示,并且容易受到 PHP 内存限制的影响。
文件的物理大小在很大程度上是无关紧要的……更重要的是要知道它包含多少个单元格(每个工作表上的行*列)。
我一直使用的“经验法则”是平均大约 1k/单元格,因此 5M 单元格工作簿将需要 5GB 内存。但是,您可以通过多种方式降低该要求。这些可以结合使用,具体取决于您需要在工作簿中访问哪些信息,以及您希望用它做什么。
如果您有多个工作表,但不需要加载所有工作表,则可以使用 setLoadSheetsOnly() 方法限制 Reader 将加载的工作表。要加载单个命名工作表:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
$sheetname = 'Data Sheet #2';
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader of which WorkSheets we want to load **/
$objReader->setLoadSheetsOnly($sheetname);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
或者您可以通过传递一组名称来一次调用 setLoadSheetsOnly() 来指定多个工作表:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
$sheetnames = array('Data Sheet #1','Data Sheet #3');
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader of which WorkSheets we want to load **/
$objReader->setLoadSheetsOnly($sheetnames);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
如果您只需要访问工作表的一部分,那么您可以定义一个读取过滤器来识别您实际想要加载的单元格:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
$sheetname = 'Data Sheet #3';
/** Define a Read Filter class implementing PHPExcel_Reader_IReadFilter */
class MyReadFilter implements PHPExcel_Reader_IReadFilter {
public function readCell($column, $row, $worksheetName = '') {
// Read rows 1 to 7 and columns A to E only
if ($row >= 1 && $row <= 7) {
if (in_array($column,range('A','E'))) {
return true;
}
}
return false;
}
}
/** Create an Instance of our Read Filter **/
$filterSubset = new MyReadFilter();
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader of which WorkSheets we want to load
It's more efficient to limit sheet loading in this manner rather than coding it into a Read Filter **/
$objReader->setLoadSheetsOnly($sheetname);
echo 'Loading Sheet using filter';
/** Tell the Reader that we want to use the Read Filter that we've Instantiated **/
$objReader->setReadFilter($filterSubset);
/** Load only the rows and columns that match our filter from $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
使用读取过滤器,您还可以以“ block ”的形式读取工作簿,这样在任何时候只有一个 block 驻留在内存中:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example2.xls';
/** Define a Read Filter class implementing PHPExcel_Reader_IReadFilter */
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;
}
}
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Define how many rows we want to read for each "chunk" **/
$chunkSize = 20;
/** Create a new Instance of our Read Filter **/
$chunkFilter = new chunkReadFilter();
/** Tell the Reader that we want to use the Read Filter that we've Instantiated **/
$objReader->setReadFilter($chunkFilter);
/** Loop to read our worksheet in "chunk size" blocks **/
/** $startRow is set to 2 initially because we always read the headings in row #1 **/
for ($startRow = 2; $startRow <= 65536; $startRow += $chunkSize) {
/** Tell the Read Filter, the limits on which rows we want to read this iteration **/
$chunkFilter->setRows($startRow,$chunkSize);
/** Load only the rows that match our filter from $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
// Do some processing here
// Free up some of the memory
$objPHPExcel->disconnectWorksheets();
unset($objPHPExcel);
}
如果您不需要加载格式信息,而只需要加载工作表数据,则 setReadDataOnly() 方法将告诉读者仅加载单元格值,忽略任何单元格格式:
$inputFileType = 'Excel5';
$inputFileName = './sampleData/example1.xls';
/** Create a new Reader of the type defined in $inputFileType **/
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
/** Advise the Reader that we only want to load cell data, not formatting **/
$objReader->setReadDataOnly(true);
/** Load $inputFileName to a PHPExcel Object **/
$objPHPExcel = $objReader->load($inputFileName);
使用单元缓存。这是一种减少每个单元所需的 PHP 内存的方法,但会以速度为代价。它通过以压缩格式或在 PHP 内存(例如磁盘、APC、内存缓存)之外存储单元对象来工作...但是您节省的内存越多,脚本执行的速度就越慢。但是,您可以将每个单元格所需的内存减少到大约 300 字节,因此假设的 500 万个单元格将需要大约 1.4GB 的 PHP 内存。
单元缓存在开发者文档的 4.2.1 节中有描述
编辑
查看您的代码,您使用的是不是特别有效的迭代器,并构建了一个单元格数据数组。您可能想查看 toArray() 方法,它已内置到 PHPExcel 中,并为您完成此操作。也看看这个 recent discussion关于构建行数据关联数组的新变体方法 rangeToArray()。
关于PHPExcel 耗尽 256、512 和 1024MB RAM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4817651/
我们认为 Cloud Foundry 中的一组虚拟机存在 Azure SNAT 耗尽问题。这些机器不经过负载平衡器。 我已经浏览过这份文件: https://learn.microsoft.com/e
我正在使用 onSceneTouchEvent 在 TMX map 上移动玩家: @Override public Scene onCreateScene() { ...
关于这篇文章:Python del Statement , 我最近遇到了以下片段: # custom_process.py import threading import subprocess myL
我有一个具有多个线程的 python 应用程序,其中线程 2 到 n 可能会打开任意数量的文件。我想确保当线程 1 尝试打开文件时,它绝对不会因为文件描述符耗尽而失败。简而言之,我想保留文件描述符而不
我开发了一个 c# .net 4 应用程序,它每天对组织中的每台计算机(超过 70,000 台)执行 WMI 查询。由于与此线程无关的原因,我无法从服务器运行该应用程序,而是从我的 Windows X
我正在尝试在 pytorch 中实现 Yolo-v2。但是,我似乎只是通过网络传递数据而耗尽了内存。该模型很大,如下所示。但是,我觉得我在用我的网络做一些愚蠢的事情(比如不在某处释放内存)。网络在 c
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我在这里查看了几个与“太多客户”相关的主题,但仍然无法解决我的问题,所以我必须针对我的具体情况再次询问。 基本上,我设置了本地 Postgres 服务器并需要进行数万次查询,所以我使用了 Python
我正在使用 std::random_device 并想检查它的剩余熵。根据 cppreference.com: std::random_device::entropy double entropy()
我有以下 docker-compos.yml 文件: web: build: . ports: - "4200:4200" - "35729:35729" vo
如果 Linux 操作系统用完进程 ID 会怎样?是否会删除较旧的进程以释放空间以适应 future 的请求? 最佳答案 我假设您问的是达到进程限制时会发生什么。在这种情况下,系统不允许创建新进程,直
我们将 Azure SQL 用作单个数据库并在 DTU 定价模型下使用。我们有一个包含约 50M 条记录的表,我们想在单个字符串属性上添加一个新的非聚集索引。 问题是这是一个生产数据库。如果我使用简单
我们有多个服务总线监听器在应用服务内作为连续的 Azure Webjobs 运行。总共有 12 个监听器 Web 作业在同一个 S1 应用服务计划上运行。环境很小,每天总共大约有~1000-10000
Der Azure 网络专家, 我们的 Web 应用程序经常耗尽出站 TCP 连接。大多数出站连接实际上是 Azure 内部连接(SQL、BlobStore、后端服务)。但我们还没有虚拟网络和专用端点
我下载了一个简单的静态网络服务器的源代码 http://www.ibm.com/developerworks/systems/library/es-nweb/sidefile1.html 但是,我对第
我已经查看了有关 SO 的其他类似问题,但无法很好地将所有内容拼凑在一起。我有一个 Rails 应用程序(在 Heroku 上),它使用具有多进程和多线程的 Puma。我的应用程序还使用 Redis
在此代码中,如果我对 ParseForm() 调用进行注释,请求将按预期工作 package main import ( "fmt" "net/http" "net/url"
我不明白。 XSLX 表大约有 3MB 大,但即使是 1024MB 的 RAM 也不足以让 PHPExcel 将其加载到内存中吗? 我这里可能做错了什么: function ReadXlsxTable
我已配置 CachingConnectionFactory包装了一个 MQTopicConnectionFactory和 MQQueueConnectionFactory每个缓存大小设置为 10。 这
我正在检查 CodeEval 中的一些问题并在 PHP 中遇到这个奇怪的错误。我没有用其他语言遇到过这样的事情,所以我不知道为什么会发生这种情况。不包括整个答案(请不要帮我找到解决方案,除了 PHP
我是一名优秀的程序员,十分优秀!