fgetcsv()
La función fgetcsv() en PHP lee una línea de un archivo y la analiza como datos CSV. Es esencial para importar archivos de texto tabulares en PHP.
Introducción a la función fgetcsv() de PHP
La función fgetcsv() en PHP lee una sola línea de un archivo abierto y la analiza como CSV (Comma-Separated Values), devolviendo los campos como un array. Es la herramienta estándar para importar exportaciones de hojas de cálculo, feeds de datos y archivos de texto tabulares en PHP.
La razón por la que se usa fgetcsv() en lugar de fgets() más explode(',', ...) es que el formato CSV es más complejo que simplemente dividir por comas. Un campo puede contener una coma si está entre comillas ("Doe, John"), un campo puede abarcar varias líneas, y las comillas dentro de un campo entre comillas se duplican (""). fgetcsv() maneja todas estas reglas automáticamente, de modo que obtienes los campos limpios sin necesidad de escribir un analizador.
Esta página cubre la firma y los parámetros, los valores de retorno y ejemplos completos ejecutables: leer un archivo completo, usar un delimitador personalizado y mapear una fila de cabecera a filas asociativas.
Sintaxis
La sintaxis de la función fgetcsv() es la siguiente:
La sintaxis de PHP fgetcsv()
array fgetcsv ( resource $stream [, int $length = 0 [, string $delimiter = ',' [, string $enclosure = '"' [, string $escape = '\\' ]]]] )stream: el puntero de archivo desde el que se leelength: la longitud máxima de la línea a leerdelimiter: el carácter delimitador para datos CSVenclosure: el carácter de cierre para datos CSVescape: el carácter de escape para datos CSV
Parámetros
La función fgetcsv() acepta un parámetro obligatorio y cuatro opcionales:
$stream: El puntero de archivo desde el que deseas leer. Este parámetro puede ser un recurso creado con la funciónfopen()o una función similar.$length: La longitud máxima de la línea a leer. Este parámetro es opcional y su valor predeterminado es 0, lo que significa que se leerá toda la línea.$delimiter: El carácter delimitador para datos CSV. Este parámetro es opcional y su valor predeterminado es ','.$enclosure: El carácter de cierre para datos CSV. Este parámetro es opcional y su valor predeterminado es '"'.$escape: El carácter de escape para datos CSV. Este parámetro es opcional y su valor predeterminado es '\'. Nota: Este parámetro está obsoleto a partir de PHP 8.1.
Valores de retorno
En caso de éxito, fgetcsv() devuelve un array indexado que contiene los campos leídos de la línea. Una línea en blanco devuelve un array con un solo campo null. Al llegar al final del archivo devuelve false, que es la señal para dejar de leer. Si el stream no es válido, también devuelve false.
Dado que tanto "fin de archivo" como "error" devuelven false, la forma idiomática de iterar es seguir llamando a fgetcsv() hasta que devuelva false, generalmente dentro de una condición while.
Ejemplos
Ejemplo 1: Leer una sola línea de datos CSV
El siguiente ejemplo abre un archivo, lee una línea de datos CSV y cierra correctamente el identificador de archivo. Siempre comprueba que fopen() tuvo éxito antes de leer:
Leer una sola línea de datos CSV
$fileHandle = fopen('data.csv', 'r');
if ($fileHandle !== false) {
$row = fgetcsv($fileHandle);
print_r($row);
fclose($fileHandle);
}Para un archivo cuya primera línea sea John,Doe,42, esto imprime:
Array
(
[0] => John
[1] => Doe
[2] => 42
)Ejemplo 2: Recorrer todas las filas de un archivo
En código real, raramente se lee una sola línea. Llama a fgetcsv() en un bucle while hasta que devuelva false para procesar el archivo completo:
Leer todas las filas de un archivo CSV
$fileHandle = fopen('data.csv', 'r');
if ($fileHandle !== false) {
while (($row = fgetcsv($fileHandle)) !== false) {
echo implode(' | ', $row), PHP_EOL;
}
fclose($fileHandle);
}La comparación estricta !== false es importante: una fila válida como ["0"] es "falsy" en PHP, por lo que un while ($row = fgetcsv(...)) sin estrictez se detendría prematuramente con datos legítimos.
Ejemplo 3: Usar un delimitador personalizado
Muchos archivos "CSV" son en realidad separados por punto y coma o por tabulaciones. Pasa el delimitador como tercer argumento (el segundo argumento, $length, puede quedarse en 0 para sin límite):
Leer datos CSV con un delimitador personalizado
// Semicolon-separated values
$row = fgetcsv($fileHandle, 0, ';');
// Tab-separated values
$row = fgetcsv($fileHandle, 0, "\t");Ejemplo 4: Mapear una fila de cabecera a arrays asociativos
Los archivos CSV suelen tener una fila de cabecera. Léela una vez y luego combínala con cada fila de datos usando array_combine() para poder acceder a los campos por nombre en lugar de por índice numérico:
Convertir un archivo CSV en filas asociativas
$fileHandle = fopen('users.csv', 'r');
if ($fileHandle !== false) {
$header = fgetcsv($fileHandle); // e.g. ['id', 'name', 'email']
while (($data = fgetcsv($fileHandle)) !== false) {
$row = array_combine($header, $data);
echo $row['name'], ' <', $row['email'], '>', PHP_EOL;
}
fclose($fileHandle);
}Errores comunes
- El parámetro
$escapeestá obsoleto. A partir de PHP 8.1, pasar un$escapeno vacío genera un aviso de obsolescencia, y PHP 9 cambiará el valor predeterminado a"". Para CSV estándar (donde las comillas se escapan duplicándolas,""), pasaescape: ""de forma explícita. - BOM UTF-8 en el primer campo. Los archivos exportados desde Excel pueden comenzar con una marca de orden de bytes, de modo que el primer campo de la cabecera puede verse como
"\u{FEFF}id". Elimínala conltrim($header[0], "\u{FEFF}")si las comparaciones fallan. auto_detect_line_endings. Los finales de línea de Mac antiguo (\r) podían confundir al analizador en versiones antiguas de PHP; esta configuracióninifue eliminada en PHP 8.1 porque el analizador ahora los maneja de forma nativa.
Funciones relacionadas
fopen()— abre el archivo antes de leerlo.fgets()— lee una línea sin procesar sin análisis CSV.fputcsv()— la operación inversa: escribe un array como una línea CSV.fclose()— cierra el identificador cuando se termina.- Manejo de archivos en PHP — el panorama general del trabajo con archivos.
Conclusión
fgetcsv() lee una línea de un archivo abierto y la analiza como CSV, devolviendo un array indexado de campos y false al final del archivo. Itera con una comprobación estricta !== false, usa array_combine() para mapear una fila de cabecera a campos con nombre, y recuerda que el parámetro $escape está obsoleto: pasa escape: "" para un análisis moderno y conforme a los estándares.