Archivos (2): leer con fgetc

Con la primitiva fgetc podemos leer caracteres de un archivo. En este vídeo cuento cómo utilizar esta función y cómo interpretar el resultado para saber si es un caracter de verdad o si estamos encontrando un error o un fin de archivo.

Cuando trabajamos con archivos en C, una de las primeras cosas que debemos entender es cómo se maneja el cursor dentro del archivo y cómo podemos leer su contenido de forma segura y controlada. Al abrir un archivo con fopen, el sistema coloca un cursor que indica la posición actual desde donde se leerá o escribirá. Este cursor funciona de manera similar a la línea que parpadea en un editor de texto, señalando el punto exacto en el archivo donde se realizará la próxima operación.

Si abrimos un archivo en modo lectura ("r"), el cursor se sitúa al principio del archivo, justo antes del primer carácter. Esto significa que la primera lectura comenzará desde el inicio. En cambio, si abrimos el archivo en modo escritura ("w"), el contenido previo se borra y el cursor también se coloca al principio, listo para escribir desde cero. Por otro lado, el modo append ("a") posiciona el cursor al final del archivo, permitiéndonos añadir contenido sin modificar lo que ya existe.

Para leer el contenido carácter a carácter, podemos usar la función fgetc. Esta función toma como argumento el descriptor del archivo y devuelve el siguiente carácter en la posición actual del cursor, desplazando el cursor una posición hacia adelante. Es importante destacar que, aunque fgetc lee un carácter, su valor de retorno es de tipo int. Esto se debe a que puede devolver un valor especial llamado EOF (End Of File), que indica que hemos llegado al final del archivo o que ha ocurrido un error en la lectura.

Veamos un ejemplo sencillo de cómo leer un archivo usando fgetc y detectar el final del archivo con EOF:

#include <stdio.h>

int main() {
    FILE *archivo = fopen("temperatura.data", "r");
    if (archivo == NULL) {
        printf("No se pudo abrir el archivo.\n");
        return 1;
    }

    int caracter_leido;
    while ((caracter_leido = fgetc(archivo)) != EOF) {
        putchar(caracter_leido);
    }

    fclose(archivo);
    return 0;
}

En este código, abrimos el archivo temperatura.data en modo lectura. Luego, en un bucle while, llamamos a fgetc para obtener cada carácter. Mientras el valor leído no sea EOF, imprimimos el carácter. Cuando fgetc devuelve EOF, significa que hemos llegado al final del archivo y salimos del bucle.

Otra forma de controlar la lectura es usando la función feof, que recibe el descriptor del archivo y devuelve un valor distinto de cero cuando el cursor está al final del archivo. Esto nos permite construir bucles que se repitan hasta que se alcance el final, aunque es recomendable usar la comparación directa con EOF para evitar imprimir caracteres inválidos.

Un detalle importante es que, al leer con fgetc, el cursor se mueve automáticamente una posición hacia adelante después de cada lectura. Esto nos permite recorrer el archivo secuencialmente sin necesidad de manipular el cursor manualmente.

Para ilustrar cómo podemos usar feof junto con fgetc, podemos escribir un bucle do-while que lea y procese cada carácter, asegurándonos de no imprimir valores inválidos:

#include <stdio.h>

int main() {
    FILE *archivo = fopen("temperatura.data", "r");
    if (archivo == NULL) {
        printf("No se pudo abrir el archivo.\n");
        return 1;
    }

    int caracter_leido;
    do {
        caracter_leido = fgetc(archivo);
        if (caracter_leido != EOF) {
            putchar(caracter_leido);
        }
    } while (!feof(archivo));

    printf("\nFin de archivo.\n");

    fclose(archivo);
    return 0;
}

Aquí, después de cada lectura, verificamos que el carácter no sea EOF antes de imprimirlo. Cuando feof indica que hemos llegado al final, salimos del bucle y mostramos un mensaje indicando que la lectura ha finalizado.

En resumen, al trabajar con archivos en C, entender el comportamiento del cursor y cómo usar funciones como fgetc, feof y la constante EOF es fundamental para leer datos de forma segura y eficiente. En capítulos posteriores, podemos profundizar en cómo manipular el cursor para posicionarnos en diferentes partes del archivo, lo que nos permitirá realizar operaciones más avanzadas como lecturas y escrituras aleatorias.

Lista de reproducción
  1. 1
    Instalar CodeBlocks
    15 minutos
  2. 2
    Funciones y hola mundo
    17 minutos
  3. 3
    Variables y tipos de datos
    17 minutos
  4. 4
    Condicionales y operadores lógicos
    16 minutos
  5. 5
    Bucles
    11 minutos
  6. 6
    Punteros
    12 minutos
  7. 7
    Arrays
    14 minutos
  8. 8
    Estructuras
    12 minutos
  9. 9
    Otras construcciones de C
    9 minutos
  10. 10
    Memoria dinámica
    8 minutos
  11. 11
    El preprocesador (parte 1)
    10 minutos
  12. 12
    El preprocesador (parte 2)
    9 minutos
  13. 13
    Archivos de cabecera y múltiples .c (parte 1)
    8 minutos
  14. 14
    Archivos de cabecera y múltiples .c (parte 2)
    9 minutos
  15. 15
    C desde la línea de comandos (parte 1)
    8 minutos
  16. 16
    C desde la línea de comandos (parte 2)
    9 minutos
  17. 17
    Break y continue
    10 minutos
  18. 18
    Goto
    13 minutos
  19. 19
    Manipulación de bits
    15 minutos
  20. 20
    Máscaras de bit
    19 minutos
  21. 21
    Archivos (1): fopen y fclose
    13 minutos
  22. 22
    Archivos (2): leer con fgetc
    9 minutos
  23. 23
    Archivos (3): fseek y ftell
    11 minutos
  24. 24
    Archivos (4): leer con fgets
    9 minutos
  25. 25
    Archivos (5): fputc y fputs
    7 minutos
  26. 26
    Archivos (6): volcar en archivos con fwrite
    10 minutos
  27. 27
    Archivos (7): fread, fwrite y los arrays
    10 minutos
  28. 28
    Archivos (8): entrada estándar y salida estándar
    9 minutos
  29. 29
    Archivos (9): buffers
    14 minutos
  30. 30
    Archivos (y 10): otras funciones útiles con archivos
    5 minutos
  31. 31
    printf (1)
    18 minutos
  32. 32
    printf (parte 2)
    12 minutos
  33. 33
    scanf (parte 1)
    17 minutos
  34. 34
    scanf (parte 2)
    17 minutos
  35. 35
    fprintf, sprintf y snprintf
    8 minutos
  36. 36
    Tipos de datos opacos
    13 minutos
  37. 37
    Bibliotecas estáticas
    13 minutos
  38. 38
    Bibliotecas dinámicas
    15 minutos
  39. 39
    Más flags: i mayúscula (include), wall, werror, pedantic...
    12 minutos
  40. 40
    pkg-config
    12 minutos
  41. 41
    Make
    17 minutos
  42. 42
    GDB
    21 minutos
  43. 43
    Variables globales
    6 minutos
  44. 44
    extern
    9 minutos
  45. 45
    Funciones variádicas
    12 minutos
  46. 46
    El optimizador de GCC y la opción -O
    12 minutos
  47. 47
    Volatile
    6 minutos