2010-08-21 38 views
14

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 1078799 bytes) in D:\xampplite\htdocs\Scraper\PHPExcel\Reader\Excel2007.php on line 269¿Cómo arreglar la memoria que se agota con PHPExcel?

Mi límite de memoria de 128M PHP se agota rápidamente incluso cuando solo estoy tratando de abrir un pequeño archivo de Excel de ~ 350 KB con PHPExcel.

Aunque, puedo aumentar el límite de memoria en la configuración, pero será genial ver si hay alguna alternativa para arreglar esto.

+4

Averigüe qué en PHP Excel está usando tanta memoria, y luego corríjala ..... – SoapBox

+1

@SoapBox: En resumen, PHPExcel - es una verdadera memoria parabólica :(Además, es una especie de biblioteca compleja, por lo que encontrar (por no hablar de solucionar) un error no es trivial. En el peor de los casos, puede ser más fácil eludir el problema y buscar una biblioteca alternativa. – Piskvor

+2

Conviértase en Microsoft Certified, solo requiere saber cómo reiniciar la máquina. liberará la memoria utilizada por el software leaky. –

Respuesta

50

tamaño del archivo no es una buena medida para los archivos del libro de trabajo cuando se trabaja con PHPExcel. La cantidad de filas y columnas (es decir, celdas) es más importante.

El código PHPExcel en sí tiene una huella de entre 10 y 25 MB, según los componentes a los que se accede.

En la actualidad, cada celda de un libro de trabajo ocupa un promedio de 1k de memoria (sin ningún almacenamiento en caché) o 1.6k en PHP de 64 bits - Supongo que PHP de 32 bits, por lo que (por ejemplo) La hoja de cálculo de 8000 líneas con 31 columnas (248,000 celdas) tendrá aproximadamente 242MB. Con el almacenamiento en caché de células (como php: // temp o DiskISAM), se puede reducir a aproximadamente un tercio, por lo que las 8000 líneas por 31 columnas requerirán aproximadamente 80 MB.

Hay una serie de opciones disponibles para ayudarle a reducir el uso de memoria:

¿Está utilizando el almacenamiento en caché de células con 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"); 

Si sólo necesita acceder a los datos en las hojas de trabajo, y no es necesario el acceso al formato de las celdas, entonces usted puede desactivar la lectura de la información de formato del libro:

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

Si sólo es necesario para acceder a algunas, pero no todas las hojas del libro, puede cargar únicamente las hojas de trabajo:

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

si solo deseas leer ciertas células dentro de las hojas de trabajo, que c un agregar un filtro:

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"); 

Todas estas técnicas pueden reducir significativamente los requisitos de memoria.

+0

5 años después: ¿su respuesta aún está actualizada? – robsch

+0

@robsch - Los archivos de Excel no han cambiado sus formatos en 5 años; los límites de memoria PHP siguen siendo los límites de memoria de PHP 5 años después; Los filtros de caché y lectura todavía existen en PHPExcel –

+0

. Es bueno saberlo. ¡Gracias! – robsch

1

Si quiere saber más, puede usar xhprof. Según este enlace, puede rastrear el uso de la memoria con él ...

3

El hecho de que el archivo de datos tenga solo X bytes no significa que utilice X bytes de RAM. Por ejemplo, solo 4K de datos en una matriz $ _SESSION usa 64K de RAM cuando se cargan. Simplemente depende de lo que el código está haciendo con esa información. La respuesta correcta es aumentar la cantidad de ram.

Además, si se trata de un archivo XLSX, son documentos XML con ZIP. Los archivos de texto se comprimen mucho más de 1/2, por lo que su archivo 350K XLSX es fácilmente un archivo de Excel de 1MB.

+0

esta fue una muy buena respuesta, lo aprendí gracias. – Chris

1

Xdebug es profiler/debugger para php y puede ayudarte a rastrear a través del uso de la memoria y las llamadas funcionales para descubrir dónde se encuentra el problema. Y es fácil de instalar, la mayoría de las distribuciones de Linux lo tienen en el repositorio, "yum install xdebug", "apt-get install xdebug".

2

PHPExcel es conocido por fugas de memoria. Yo le aconsejo que use los siguientes elementos que necesitan una fracción de la memoria que utiliza PHPExcel:.

1) para la lectura: PHP-Excel-Reader

2) Por escritura: Pear Spreadsheet Excel Writer

+0

De acuerdo con el sitio web vinculado "Spreadsheet_Excel_Writer está fuera fechado y necesita una reescritura completa. Si desea ayudar con esta tarea, póngase en contacto con nosotros. De lo contrario, no recomendamos este paquete para el nuevo desarrollo. " – Isius

+0

PHP-Excel-Reader también funciona para Excel 2007? – logan

+0

Para escritura: [PHP_XLSXWriter] (https://github.com/mk-j/PHP_XLSXWriter) uso de memoria 95% más bajo que PHPExcel. – velcrow

1

Una cosa que debes tener en cuenta es que las celdas están vacías.

Tuve el mismo problema, solo 800 filas de datos y el script no fue capaz de leer. Ambos errores de tiempo de espera y memoria insuficiente cuando se corrigieron.

Algo @Mark Baker dijo acerca de las células me hizo pensar. Noté que tenía muchas células vacías y solo copié las celdas con datos en un nuevo libro de trabajo para que se ejecutara en un segundo.

Espero que esto ayude a alguien.

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

Este código es mucho suficientes

0

Este post habla acerca de cómo cerrar un lector PHPExcel: How to close excel file in php-excel-reader Si va a abrir varios archivos de Excel al mismo tiempo, pero en realidad no necesitan todo eso a la vez , entonces podría tratar de abrir y cerrar (es decir, desarmar) los lectores de cada archivo uno por uno. Por cierto, usar el mismo nombre de variable para los lectores sería suficiente para la operación de "desarmado".

Cuestiones relacionadas