Как исправить истощение памяти с помощью PHPExcel? - PullRequest
20 голосов
/ 21 августа 2010

Неустранимая ошибка: допустимый объем памяти 134217728 байт исчерпан (попытка выделить 1078799 байт) в D: \ xampplite \ htdocs \ Scraper \ PHPExcel \ Reader \ Excel2007.php в строке 269

Мое ограничение памяти 128М PHP быстро исчерпывается, даже когда я пытаюсь открыть небольшой файл Excel размером ~ 350 КБ с помощью PHPExcel.

Хотя я могу увеличить предел памяти в конфигурации, но было бы замечательно увидеть, есть ли альтернативы, чтобы это исправить.

Ответы [ 8 ]

55 голосов
/ 22 августа 2010

Размер файла не подходит для работы с книгами при работе с PHPExcel.Количество строк и столбцов (т. Е. Ячеек) является более важным.

Сам код PHPExcel имеет размер от 10 до 25 МБ, в зависимости от того, к каким компонентам осуществляется доступ.

В настоящее времякаждая ячейка в рабочей книге занимает в среднем 1 КБ памяти (без кеширования) или 1,6 КБ на 64-битном PHP - на данный момент я предполагаю 32-битный PHP - поэтому (например) рабочий лист из 8000 строк с 31 столбцом(248 000 ячеек) будет около 242 МБ.При использовании кэширования ячеек (например, php: // temp или DiskISAM) этот показатель может быть уменьшен примерно до трети, поэтому для 8000 строк на 31 столбец потребуется около 80 МБ.

Существует несколько вариантов, доступных дляпомочь вам сократить использование памяти:

Используете ли вы кэширование ячеек с 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");

Все эти методы могут значительно снизить требования к памяти.

4 голосов
/ 21 августа 2010

PHPExcel известен утечками памяти.Я советую вам использовать следующее, для которого требуется ФРАКЦИЯ памяти, которую PHPExcel использует .:

1) Для чтения: PHP-Excel-Reader

2) Для записи: Грушевая таблица Excel Writer

3 голосов
/ 21 августа 2010

То, что файл данных содержит только X байтов, не означает, что он использует X байтов памяти.Например, только 4 КБ данных в массиве $ _SESSION используют 64 КБ ОЗУ при загрузке.Это зависит только от того, что код делает с этими данными.Правильный ответ - увеличить количество оперативной памяти.

Кроме того, если это XLSX-файл, это ZIP-документы XML.Текстовые файлы сжаты намного быстрее, чем 1/2, так что ваш файл XLSX размером 350 КБ легко превратится в файл Excel размером 1 МБ.

1 голос
/ 26 сентября 2012

Стоит также обратить внимание на пустые ячейки.

У меня была та же проблема, только 800 строк данных, и сценарий даже не смог прочитать. И тайм-ауты и ошибки нехватки памяти, когда любой из них был исправлен.

Что-то, сказанное Марком Бейкером о клетках, заставило меня задуматься. Я заметил, что у меня было множество пустых ячеек, и копирование только ячеек с данными в новую рабочую книгу позволило запустить ее за секунду.

Надеюсь, это кому-нибудь поможет.

1 голос
/ 21 августа 2010

Xdebug является профилировщиком / отладчиком для php и может помочь вам отслеживать использование памяти и функциональные вызовы, чтобы выяснить, в чем проблема. И его легко установить, большинство дистрибутивов Linux имеют его в репозитории, "yum install xdebug", "apt-get install xdebug".

1 голос
/ 21 августа 2010

Если вы хотите узнать, вы можете использовать xhprof .По этой ссылке вы можете отслеживать использование памяти по ней ...

0 голосов
/ 24 октября 2017

В этом посте рассказывается, как закрыть программу чтения PHPExcel: Как закрыть файл Excel в php-excel-reader Если вы открываете несколько файлов Excel одновременно, но на самом деле они не нужны одновременноВремя, затем вы можете попытаться открыть и закрыть (то есть сбросить) считыватели для каждого файла по одному.Кстати, для операции «unsetting» будет достаточно использовать одно и то же имя переменной для читателей.

0 голосов
/ 05 августа 2016
$objReader = PHPExcel_IOFactory::createReader('Excel2007');
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load("test.xlsx");

Этого достаточно кода

...