Modulo 09 — Lectura y escritura de archivos en C

Idea central

Hasta ahora todos los datos vivian en RAM: al terminar el programa, desaparecian. Los archivos resuelven eso: permiten que un programa persista datos entre ejecuciones y comparta informacion con otros programas. La API de archivos de C es sencilla: abrir → operar → cerrar.

Que aprendes

ConceptoPara que sirve
fopen(ruta, modo)Abrir un archivo; devuelve un puntero FILE *
Modos "r", "w", "a"Leer / escribir (crea/trunca) / anadir al final
Comprobar NULLDetectar error al abrir (archivo no existe, sin permisos…)
fprintf(fp, ...)Escribir en archivo con el mismo formato que printf
fscanf(fp, ...)Leer datos formateados desde archivo
fgets(buf, n, fp)Leer una linea completa (con espacios) de forma segura
fclose(fp)Cerrar el archivo y volcar los buffers a disco

Explicacion

Patron general (siempre el mismo)

1. Declarar  FILE *fp;
2. Abrir     fp = fopen("ruta", "modo");
3. Comprobar if (fp == NULL) { /* error */ }
4. Operar    fprintf / fscanf / fgets / ...
5. Cerrar    fclose(fp);

Modos de apertura

ModoLeeEscribeCrea si no existeTrunca si existe
"r"sinonono
"w"nosisisi
"a"nosi (solo final)sino
"r+"sisinono

Sintaxis minima

#include <stdio.h>
 
FILE *fp = fopen("datos.txt", "w");
if (fp == NULL) {
    printf("Error al abrir el archivo\n");
    return 1;          // salir con codigo de error
}
 
fprintf(fp, "Hola, archivo!\n");
fclose(fp);

Leer lineas con fgets

char linea[256];
FILE *fp = fopen("datos.txt", "r");
if (fp == NULL) return 1;
 
while (fgets(linea, sizeof(linea), fp) != NULL) {
    printf("%s", linea);   // linea ya incluye '\n'
}
fclose(fp);

fgets devuelve NULL al llegar al final del archivo (EOF), lo que hace el bucle while natural.

Leer numeros con fscanf

int n;
while (fscanf(fp, "%d", &n) == 1) {   // == 1: leyo un entero correctamente
    printf("%d\n", n);
}

Worked example

Problema: Pedir al usuario 3 nombres, guardarlos en nombres.txt, volver a abrirlo y mostrarlos numerados.

#include <stdio.h>
#include <string.h>
 
int main(void) {
    // --- PASO 1: escribir 3 nombres ---
    FILE *fw = fopen("nombres.txt", "w");
    if (fw == NULL) {
        printf("No se pudo crear el archivo\n");
        return 1;
    }
 
    char nombre[64];
    for (int i = 0; i < 3; i++) {
        printf("Nombre %d: ", i + 1);
        scanf("%63s", nombre);
        fprintf(fw, "%s\n", nombre);   // una linea por nombre
    }
    fclose(fw);   // SIEMPRE cerrar antes de volver a abrir
 
    // --- PASO 2: leer y mostrar numerados ---
    FILE *fr = fopen("nombres.txt", "r");
    if (fr == NULL) {
        printf("No se pudo leer el archivo\n");
        return 1;
    }
 
    printf("\n--- Contenido del archivo ---\n");
    int linea = 1;
    char buf[64];
    while (fgets(buf, sizeof(buf), fr) != NULL) {
        // fgets conserva el '\n'; quitarlo para mostrar limpio
        buf[strcspn(buf, "\n")] = '\0';
        printf("%d. %s\n", linea++, buf);
    }
    fclose(fr);
    return 0;
}

Por que funciona paso a paso:

  1. Abrimos con "w" → crea/trunca nombres.txt.
  2. fprintf(fw, "%s\n", nombre) escribe cada nombre seguido de salto de linea.
  3. fclose(fw) vuelca los buffers; sin esto el archivo puede quedar vacio.
  4. Abrimos con "r" → el archivo ya tiene datos.
  5. fgets lee hasta \n o sizeof(buf)-1 caracteres; al llegar a EOF devuelve NULL y el while termina.
  6. strcspn(buf, "\n") devuelve el indice del primer \n; ponerlo a '\0' lo elimina.

Salida ejemplo:

Nombre 1: Ana
Nombre 2: Bruno
Nombre 3: Carla

--- Contenido del archivo ---
1. Ana
2. Bruno
3. Carla

Errores tipicos en C

#ErrorPor que falla
1No comprobar fopen == NULLEl programa peta con segfault si el archivo no existe
2Olvidar fcloseLos datos pueden no llegar a disco (el buffer se descarta)
3Usar "w" cuando quieres anadirModo "w" trunca: pierdes todo el contenido previo
4fscanf sin & en variables escalaresLee a direccion invalida → comportamiento indefinido
5fgets con buffer demasiado pequenoTrunca la linea; el \n queda en el stream para la siguiente lectura

Ejercicios

Practica lo de este módulo. Cada enlace abre el ejercicio con su enunciado, diagrama de flujo, explicación y el código listo para copiar.

Conexiones

  • 00_README
  • MOC_Linux
  • 08-structs — modulo anterior: structs que ahora podras persistir en disco
  • (Modulo 10 por definir) — siguiente paso