Leer ficheros CSV enormes en PHP
Continúo con mi serie de posts sobre ficheros grandes. Tras descargar ficheros CSV enormes en local, me tocó leerlos y procesarlos. Imaginemos el siguiente código:
public function processFile(string $fileName)
{
// descargamos el fichero con el método del post anterior
$this->downloadFile($fileName);
foreach ($this->rows($fileName) as $row) {
$this->process($row);
}
}
La clave está en este método rows
. En este método, vamos a leer el fichero CSV línea a línea y vamos a ir devolviendo cada línea a través de un generator:
public function rows(string $fileName)
{
$local = Storage::disk('local');
$handle = fopen($local->path($fileName), 'r');
$header = null;
while (($line = fgets($handle)) !== false) {
$row = str_getcsv($line, ";");
if (is_null($header)) {
$header = $row;
continue;
}
$row = array_combine($header, $row);
yield $row;
}
fclose($handle);
}
En este método hacemos lo siguiente:
- Inicializar el disco local
- Abrir el fichero
$fileName
en modo lectura con un puntero - Comenzar a leer el fichero línea a línea
- La primera línea, la guardamos en la variable
$header
- El resto de líneas las combinamos con el
$header
para tener un array asociativo - Devolvemos cada fila, de una en una, a través de
yield $row
. Esto hará que no consumamos apenas memoria, ya que cada fila se procesa de una en una y no se van acumulando en memoria. - Una vez terminamos, cerramos el fichero