Parsear ficheros CSV en PHP
Desde que en Agosto cambié de empresa me he encontrado muchas veces con la necesidad de parsear ficheros CSV. Hace un tiempo que empecé a evaluar a nuevos candidatos y a todos les hacía la misma pregunta: ¿Cómo parsearías un fichero CSV? La respuesta más común a esta pregunta suele ser “con expresiones regulares” pero en este post voy a tratar de explicar la manera más sencilla, y a la vez potente, de parsear este tipo de ficheros.
Desde la versión 4 de PHP existen dos funciones muy útiles para estos menesteres, fgetcsv y fputcsv.
Según la documentación PHP la firma de esta función es la siguiente:
array fgetcsv (resource $handle [,int $length [,string $delimiter = ',' [,string $enclosure = '"' [,string $escape = '\\']]]])
Como podemos ver, el primer parámetro a proporcionar es el puntero al fichero que queremos leer y después toda una serie de parámetros opcionales como la dimensión de la cadena a leer, el delimitador de campos, el carácter de envoltorio de campos y el carácter para escapar símbolos poco comunes. Esta función, al ser llamada con los parámetros correctos, devolverá la línea que ha leído en formato de array, donde cada campo será una nueva entrada en el array.
Bien, en este punto y antes de mostrar un trozo de código tengo que hacer mención a un detalle, esta función puede ocasionar algunos problemas dependiendo del sistema operativo en el que estemos corriendo PHP. En mi caso, utilizando Mac OS X Snow Leopard, me he encontrado que la función no detecta bien el final de la línea con lo cuál, y para ahorrarnos problemas, vamos a utilizar también la siguiente instrucción:
ini_set('auto_detect_line_endings', TRUE);
Esta línea lo que hace es forzar a detectar el final de línea, lo que resuelve el problema en dichas plataformas.
Dicho todo esto, voy a mostrar un trozo de código que lo que hace es recorrer el fichero y generar una array de arrays con todo el fichero parseado.
<?php
//Prepare the auto detect line endings for some OS's
ini_set('auto_detect_line_endings', TRUE);
//Save the path to the file we want to open
$file = dirname(__FILE__) . 'test.csv';
//Create a file pointer to de file in read mode
$fp = fopen($file, 'r');
//Setup the result var
$parsedCSV = array();
/* Get the headers of the csv and store it in a special key in the array. Setting the max length to 0 strip the length constrain */
$parsedCSV['headers'] = fgetcsv($fp, 0, ',');
/* Loop to read the entire file, take a look at the comparison and remember that if fgetcsv arrives at the end of the file a FALSE will be returned. We use this to detect the EOF */
while(($line = fgetcsv($fp, 0, ',')) !== FALSE){
$parsedCSV[] = $line;
}
//Print out the array
die(var_dump($parsedCSV));
Para detectar el final de fichero en este script estamos usando la comparación ($line = fgetcsv($fp, 0, ‘,’)) !== FALSE ya que fgetcsv devuelve FALSE en caso de error o EOF (End Of File).
Espero que este post os sea de ayuda y recordad que podéis preguntarnos mediante el sistema de comentarios.


Enero 4th, 2010 a las 1:20
Información Bitacoras.com…
Valora en Bitacoras.com: Desde que en Agosto cambié de empresa me he encontrado muchas veces con la necesidad de parsear ficheros CSV. Hace un tiempo que empecé a evaluar a nuevos candidatos y a todos les hacía la misma pregunta: ¿Cómo parsearías un …..
Enero 6th, 2010 a las 4:15
No conocía la existencia de fgetcsv fputcsv. Muy sencillo, tener una pequeña clase auxiliar para manejo de información csv-bbdd y viceversa parece que sería bastante fácil de tener.
Saludos