- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我在处理 XLS 文件时遇到了 PHPExcel 的内存问题。我必须处理相当大的文件(50k 到 200k 行,9-10 列)所以我不得不使用 ReadFilters 来解决内存问题。
但是,尽管它与 XLSX 文件配合得很好,但使用混合后台进程和一些简单的 block 大小计算,我无法使其与 XLS 文件配合使用。
这是一段让一切都爆炸的代码:
Class ExcelReadFilter implements PHPExcel_Reader_IReadFilter
{
private $startRow = 0;
private $endRow = 0;
public function setRows($startRow, $chunkSize) {
$this->startRow = $startRow;
$this->endRow = $startRow + $chunkSize;
}
public function readCell($column, $row, $worksheetName = '') {
if ( ($row >= $this->startRow && $row < $this->endRow) ) {
return true;
}
return false;
}
}
PHPExcel_Settings::setCacheStorageMethod( PHPExcel_CachedObjectStorageFactory::cache_in_memory_serialized );
....
$filter = new ExcelReadFilter();
$filter->setRows($desde, $cuantas);
$reader = PHPExcel_IOFactory::createReader($this->file_type);
$reader->setLoadSheetsOnly($sheet_name);
$reader->setReadDataOnly(false);
$reader->setReadFilter($filter);
$chunk = $reader->load($this->file);
$chunk->setActiveSheetIndexByName($sheet_name);
$active_sheet = $chunk->getActiveSheet();
$rowIterator = $active_sheet->getRowIterator($desde);
$this->num_filas = $active_sheet->getHighestRow();
在那之后,我立即加入了以下几行,以便更好地了解发生了什么:
ob_start();
var_dump($rowIterator);
$f = fopen("excel-info.txt", "w");
fwrite($f, ob_get_clean());
fclose($f);
ob_end_clean();
die;
而且我认为它指出了内存问题所在。当我第一次上传原始XLS文件时,excel-info.txt的大小为13M。然后我打开XLS文件另存为XLSX,重复这个过程,之后excel-info.txt就只有285k了。
有什么方法可以修改这些过滤器以处理 XLS 文件?
哦,将 PHP 内存限制设置为更高的值不是一个选项,但执行时间并不重要。
已添加
当我使用不同的内存缓存选项时,我能够将内存使用量减少到足以使其正常工作,并在大多数情况下将其保持在可接受的大小。
现在,我正在使用 PHPExcel_CachedObjectStorageFactory::cache_to_sqlite,它似乎足以让它工作。
我想说明一下,我对文件中的序列化信息所做的计算是不正确的。Excel5 文件生成一个数组,其中记录的行数与 excel 文件的所有不满足过滤条件的值都设置为 NULL 的行数相同。当然,当我将它保存到文本文件时,会出现类似...
array(10) {
["A"]=>
NULL
["B"]=>
NULL
["C"]=>
NULL
["D"]=>
NULL
["E"]=>
NULL
["F"]=>
NULL
["G"]=>
NULL
["H"]=>
NULL
["I"]=>
NULL
["J"]=>
NULL
}
...在文件中占用大量空间,但不应该在 php_memory 中,所以这是我的错。
现在,我正在使用这段代码来跟踪内存使用情况:
for ( $i=1; $i < 20000; $i+=5000 ){
$filter->setRows($i, 5000);
echo "\n1- Usage: ".(memory_get_usage ()/1024)/1024;
$objPHPExcel = $reader->load($this->file);
echo "\n2- Usage: ".(memory_get_usage ()/1024)/1024;
$sheetData = $objPHPExcel->getActiveSheet()->toArray(null,true,true,true);
unset($sheetData);
unset($objPHPExcel);
echo "\n3- Usage: ".(memory_get_usage ()/1024)/1024;
}
对于某个XLS文件,它显示:
第一次迭代1- 用法:4.38596343994142- 用法:34.2926712036133- 用法:34.68034362793
第二次迭代1- 用法:34.680343627932- 用法:34.682937622073- 用法:34.684982299805
保存为 XLSX 后的同一个文件:
第一次迭代1- 用法:4.27809906005862- 用法:6.90421295166023- 用法:7.2916641235352
第二次迭代1- 用法:7.29166412353522- 用法:7.51154327392583- 用法:7.2813568115234
但是,我必须说,在保存为 XLSX 后,大小减少了大约一半,因此我不能说这是一个错误还是预期的行为。
最佳答案
PHPExcel 是一个内存大户。我已经将它用于几个客户端,发现您必须尝试 php 内存限制设置以找到它可以加载客户端可能导入的平均文件的最佳位置。我不得不在某些项目中使用多达 8 GB 的空间。当然,您可以在加载 xls 文件的例程中使用ini_set('memory_limit','16M'),不在php.ini文件中。
您尝试过 setReadDataOnly(true) 吗?
我认为原因是 xls 文件不仅是 csv 数据,而且包含许多其他信息(如字体和宏)。当您加载文件时,PHPExcel 会尝试将所有部分加载到内存中,从而创建一个巨大的结构。
关于PHPExcel 仅对 XLS 文件超出内存使用量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25951222/
在文档中我们可以找到 The limits are based on a moving window that tracks the number of requests you send per h
我试图了解使用 Windows Azure 托管 Web 服务的正确方法。在阅读了一些可用的文档后,我已经达到以下几行: Windows Azure takes the following actio
我正在使用 unboundid ldap sdk 来执行 ldap 查询。运行 ldap 搜索查询时遇到一个奇怪的问题。当我对包含 50k 个条目的组运行查询时出现异常。我的异常(exception)
我有以下 docker-compose 文件: version: "2.4" services: auto_check: image: python mem_limit: 97M
我有副本集(托管在亚马逊上),其中有: 主要 中学 仲裁者 它们都是 3.2.6 版本,这个副本正在我的分片集群中创建一个分片(如果这很重要,尽管我认为它不重要)。 当我在 primary 上键入 r
我知道在 C++ 中访问缓冲区边界是未定义的行为。 这是来自 cppreference 的示例: int table[4] = {}; bool exists_in_table(int v) {
嗨,我有一个表单的 div。我希望当鼠标离开 div 时禁用单击事件。所以我尝试了这个,但它不起作用,div 仍然可以点击。有什么想法吗?? var flag = false; $("#foo").l
我正在使用我的客户端获取有关存储在我的 Swift 对象存储中的某个文件的一些信息,该文件可以通过 REST Api 访问。在 Swift 中,指向指定对象的 HEAD 方法和 url 返回它的元数据
如何在 Excel 的 CONCATENATE 函数中使用超过 255 个字符?我实际上也在 EXCEL 的 HYPERLINK 函数中使用 CONCATENATE 函数。一个例子如下: =HYPER
在 java 6 web 应用程序中,我尝试从执行的命令中检索大量输出。我在 javaworld article 上“借用/窃取/基于”它。我面临的问题是,由于输出被截断,长度似乎超出了大小限制。我已
我有一个更改事件,当选择框更改时会触发该事件。然而,选择框位于被替换的 div 内,因此会重新生成选择框。由于此错误可能是由于无限循环造成的,因此我猜测创建选择框时也必须触发我的触发事件。我尝试了很多
我正在 visual studio 2013 中用 c# 创建一个网络服务。我已连接到数据库并使用以下代码返回 json。 [WebMethod] [ScriptMethod(ResponseForm
我使用 php 脚本解析远程 xml 文件并将网页上的输出打印到 div 中。由于我需要输出必须与当前播放的轨道同步,所以我使用 Javascript 每 20 秒重新加载一次 div 内容。在测试页
#define MAX_BUFF_SIZE 64 char input[MAX_BUFF_SIZE]; int inSize = read(0, input, MAX_BUFF_SIZE); if
我在申请公司时遇到了问题。 我将总结系统的关键要素: 我公司的系统几年前就在 Windows XP 和 7(家庭版、专业版、基本版)机器上运行。 它是用 .NET 4.0 编写的,基于 WCF。 它使
我有一个渲染循环,用于监听数位板输入并从顶点/索引缓冲区(以及其他内容)中绘制。顶点数据可以增长,当它达到一定水平时,DispatchMsg(&msg) 会遇到这种情况: Unhandled exce
我通过 Postgres JDBC 驱动程序使用 Java 1.7 和 Postgres。将从 Web 服务使用数据库连接。在测试中,我得到了以下错误: FATAL: connection limit
我想知道当超过 Firebase 实时数据库的限制时会发生什么。问题是我知道我可以拥有的最大连接数仅为 100。现在,假设我的 Android 应用程序有 1,000 个活跃用户,并且我实现了实时数据
我正在将一组图像上传到我的 node.js Express 服务器,但收到错误 - “错误:超出 maxFieldsSize”。看起来默认的 maxFieldsSize 是 2MB。我需要能够上传最多
我正在使用 Django 构建一个小型 Web 项目,该项目有一个包含 ImageField 的模型 (Image)。当我尝试使用管理界面上传图片时,我遇到了这个问题(删除了个人身份信息): Runt
我是一名优秀的程序员,十分优秀!