php - pueden - Error de memoria insuficiente al leer un archivo grande
no se puede abrir la ilustracion no hay suficiente espacio para la ventana (4)
Tengo un gran csv que quiero analizar e insertar en mi base de datos. Tengo este PHP:
$target = ''../uploads/''.$f;
$handle = fopen($target, "r");
$data = fgetcsv($handle, 0, ",");
$rows = array();
while ($data !== FALSE) {
$rows[] = $data;
}
fclose($handle);
if (count($rows)) {
foreach ($rows as $key => $value) {
echo $value;
}
}
Cada vez que intento ejecutar mi script obtengo este error:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 35 bytes)
¿Alguna idea de como hacer esto?
Use mysqlimport en su lugar
Si bien puede analizar y generar consultas con PHP, obtendrá un mejor rendimiento al permitir que MySQL lo maneje directamente. Su base de datos se lo agradecerá.
<?php
exec("mysqlimport mysqlimport [options] db_name textfile1");
?>
Fuentes:
Creo que esta parte es incorrecta:
$data = fgetcsv($handle, 0, ",");
$rows = array();
while ($data !== FALSE) {
$rows[] = $data;
}
Una llamada a fgetcsv
lee una línea desde $handle
. Debes poner fgetcsv
en la condición de bucle:
$handle = fopen($target, "r");
$data = fgetcsv($handle, 0, ",");
while (($row = fgetcsv($handle, 0, ",")) !== FALSE) {
// Example insert - obviously use prepared statements/escaping/another DAL
$db->query("INSERT INTO tbl (columns..) VALUES ({$row[0]}, {$row[1]} ... )");
}
Use la instrucción estándar LOARCH DATA INFILE de MySQL para escapar de leer / analizar / insertar datos a través de PHP:
function import_csv( $table, $afields, $filename, $delim = '','', $enclosed = ''"'', $escaped = ''//', $lineend = ''//r//n'', $hasheader = FALSE) {
if ( $hasheader ) $ignore = "IGNORE 1 LINES ";
else $ignore = "";
$q_import =
"LOAD DATA INFILE ''" . $_SERVER[''DOCUMENT_ROOT''] . $filename . "'' INTO TABLE " . $table . " " .
"FIELDS TERMINATED BY ''" . $delim . "'' ENCLOSED BY ''" . $enclosed . "'' " .
" ESCAPED BY ''" . $escaped . "'' " .
"LINES TERMINATED BY ''" . $lineend . "'' " . $ignore . "(" . implode('','', $afields) . ")"
;
return mysql_query($q_import);
}
En este caso, no necesita abrir / leer el archivo CSV en PHP, MySQL manejará la importación de datos por sí mismo.
No es necesario que lea todos los datos csv del archivo en la memoria antes de procesarlos.
En su lugar, crea un ciclo while que lea de tu archivo una línea a la vez. Cada vez que lea del archivo, debe insertar una fila en su base de datos.
O lea varias líneas e inserte varias filas a la vez.
Ejemplo:
$i = 0;
while (($data = fgetcsv($handle, 0, ",") !== FALSE) {
$rows[] = $data;
$i++;
// insert 100 rows at one time.
if ($i % 100 === 0) {
//insert these rows to db
insert_to_db($rows);
//then reset $rows
$rows = array();
}
}
insert_to_db($rows);