Saltar al contenido
Portada » C/C++ » 9. Archivos en C/C++

9. Archivos en C/C++

Archivos en C/C++. Hasta ahora, todos los programas han intercambiado datos únicamente con la memoria y la consola; en este capítulo aprenderemos a leer y escribir información de forma permanente mediante archivos en disco. Veremos la diferencia entre archivos de texto (legibles por humanos) y archivos binarios (datos en bruto), y utilizaremos funciones de la biblioteca estándar —como fopen, fscanf, fread, fwrite y fclose— para manipularlos.

Veremos los modos de apertura ("r", "w", "a", "rb", etc.), cómo leer y escribir línea a línea o en bloques, y las técnicas básicas para detectar y manejar errores etc. Vamos!!!!

9.1 Archivos de texto y binarios

En C y C++, existen dos formas principales de trabajar con archivos: archivos de texto y archivos binarios. Ambos se utilizan para almacenar datos en disco, pero difieren en su estructura, forma de lectura/escritura, y propósito.

Archivos de Texto

Un archivo de texto almacena la información como una secuencia de caracteres legibles por humanos. Esto incluye números, letras, signos de puntuación y saltos de línea, codificados normalmente en ASCII o UTF-8.

Ventajas:

  • Legibles y editables con cualquier editor de texto.
  • Fáciles de depurar y compartir.
  • Útiles para registros, configuraciones, logs, CSV, etc.

Desventajas:

  • Menor eficiencia: cada número o dato se convierte en caracteres (por ejemplo, el número 12345 se guarda como cinco bytes: '1', '2', '3', '4', '5').
  • Conversión constante entre texto ↔ valores internos del programa.

Ejemplo de creación y escritura:

#include <stdio.h>

int main() {
FILE *archivo = fopen("datos.txt", "w"); // Abrir archivo en modo escritura

if (archivo == NULL) {
printf("Error al abrir el archivo.\n");
return 1;
}

fprintf(archivo, "Nombre: Juan\n");
fprintf(archivo, "Edad: %d\n", 25);

fclose(archivo); // Cerrar el archivo
return 0;
}

Este archivo tendrá un contenido fácilmente legible:

Nombre: Juan
Edad: 25

Archivos Binarios

Un archivo binario almacena datos tal como están representados en memoria, sin conversión a caracteres. Es decir, los valores se guardan en formato binario bruto, lo cual es más eficiente pero no legible para humanos.

Ventajas:

  • Ocupan menos espacio.
  • Lectura y escritura más rápidas.
  • Permiten almacenar estructuras completas o datos complejos (como imágenes, estructuras de datos, audio, video, etc.).

Desventajas:

  • No son legibles sin un programa que los interprete.
  • Pueden ser incompatibles entre plataformas (por ejemplo, por diferencias de tamaño de tipos de datos).

Ejemplo de escritura binaria:

#include <stdio.h>

int main() {
FILE *archivo = fopen("datos.bin", "wb"); // w = write, b = binary

if (archivo == NULL) {
printf("No se pudo abrir el archivo.\n");
return 1;
}

int edad = 25;
fwrite(&edad, sizeof(int), 1, archivo); // Guarda los 4 bytes de la variable edad

fclose(archivo);
return 0;
}

Este archivo no será legible directamente en un editor de texto, pero es muy útil para almacenamiento eficiente de datos binarios.

Diferencias clave entre texto y binario

CaracterísticaArchivos de TextoArchivos Binarios
LegibilidadAlta (para humanos)Baja (requiere programa)
Espacio en discoMayorMenor
Velocidad de accesoMás lenta (requiere parseo)Más rápida (acceso directo)
Conversión de datosRequiere conversión (ej. int ↔ string)No necesita conversión
PortabilidadAltaMedia/baja (según plataforma)
Uso típicoLogs, CSV, configsBases de datos, imágenes, estructuras

9.2 Funciones básicas de archivo en C/C++

C proporciona un conjunto de funciones en la librería <stdio.h> (Standard Input Output library) para manipular archivos de manera sencilla. En este apartado vamos a explicar las más importantes relacionadas con la gestión de archivos y cómo se usan.

📁 fopen()

La función fopen() abre un archivo y devuelve un puntero a una variable de tipo FILE, que se utiliza en el resto de operaciones (leer, escribir, cerrar…).

FILE *fopen(const char *nombre_archivo, const char *modo);
  • nombre_archivo: nombre (y ruta opcional) del archivo.
  • modo: especifica cómo se abrirá el archivo.

Modos comunes:

ModoSignificado
"r"Lectura (debe existir el archivo)
"w"Escritura (crea o sobrescribe archivo)
"a"Escritura al final del archivo (append)
"rb"Lectura binaria
"wb"Escritura binaria

Ejemplo:

FILE *archivo = fopen("ejemplo.txt", "r");
if (archivo == NULL) {
printf("No se pudo abrir el archivo.\n");
}

🧾 fscanf() y fprintf()

Estas funciones permiten leer y escribir archivos de texto, igual que scanf y printf lo hacen con la consola, salvo que en este caso, debemos facilitar como parámetro el puntero de tipo FILE que hemos obtenido a la hora de abrir el archivo con fopen().

fprintf() – escribir en archivos de texto

fprintf(archivo, "Nombre: %s\nEdad: %d\n", nombre, edad);

fscanf() – leer de archivos de texto

fscanf(archivo, "%s %d", nombre, &edad);

Veamos un ejemplo completo:

#include <stdio.h>

int main() {
FILE *archivo = fopen("datos.txt", "w");

if (archivo == NULL) {
printf("Error al abrir archivo\n");
return 1;
}

char nombre[] = "Lucía";
int edad = 30;
fprintf(archivo, "%s %d\n", nombre, edad);
fclose(archivo);
return 0;
}

Y luego:

#include <stdio.h>

int main() {
FILE *archivo = fopen("datos.txt", "r");

if (archivo == NULL) {
printf("No se pudo leer archivo\n");
return 1;
}

char nombre[50];
int edad;
fscanf(archivo, "%s %d", nombre, &edad);

printf("Nombre: %s, Edad: %d\n", nombre, edad);
fclose(archivo);
return 0;
}

fwrite() y fread() – Archivos Binarios

Estas funciones permiten leer y escribir datos directamente en binario, muy útiles para estructuras, arrays, imágenes, etc.

fwrite() – escribir datos binarios

Al invocar a esta función deberemos indicar la dirección de memoria donde está la información a escribir, el tamaño en bytes de la información a escribir, número de elementos y el puntero del archivo que obtuvimos con la función fopen().

fwrite(&edad, sizeof(int), 1, archivo);
  • 1: número de elementos.
  • sizeof(int): tamaño de cada elemento.

fread() – leer datos binarios

Al invocar a esta función deberemos indicar la dirección de memoria donde alojar la información leída del archivo, el tamaño en bytes de la información a leer, número de elementos y el puntero del archivo que obtuvimos con la función fopen().

cCopiarEditarfread(&edad, sizeof(int), 1, archivo);

Ejemplo:

#include <stdio.h>

int main() {
FILE *archivo = fopen("datos.bin", "wb");
int numero = 12345;

fwrite(&numero, sizeof(int), 1, archivo);
fclose(archivo);
return 0;
}

Y para leerlo:

#include <stdio.h>

int main() {
FILE *archivo = fopen("datos.bin", "rb");
int numero;

fread(&numero, sizeof(int), 1, archivo);
printf("Número leído: %d\n", numero);
fclose(archivo);
return 0;
}

fclose()

Es fundamental cerrar el archivo una vez terminado el trabajo para liberar recursos y asegurar que los datos se escriben correctamente:

fclose(archivo);

Comprobación de errores

Es importante que siempre verifiquemos que fopen() no devuelve NULL, ya que eso indica que el archivo no se pudo abrir (porque el archivo no exista, porque no tengamos permisos, haya errores en disco, etc.)

if (archivo == NULL) {
perror("Error al abrir archivo"); // imprime error del sistema
return 1;
}

9.3. Lectura y escritura línea a línea en archivos de texto

En este apartado aprenderás a leer y escribir archivos de texto línea por línea, lo cual es muy útil cuando se trabaja con contenido estructurado (como listas de nombres, configuraciones, registros, etc.).


🔹 Escritura línea a línea con fprintf()

Veamos ahora como podemos hacer para escribir líneas completas en un archivo usamos la función fprintf(). Basta con añadir un \n al final de la cadena para insertar un salto de línea.

Ejemplo: Escribir varias líneas

#include <stdio.h>

int main() {
FILE *archivo = fopen("nombres.txt", "w");

if (archivo == NULL) {
printf("No se pudo abrir el archivo para escritura.\n");
return 1;
}

fprintf(archivo, "Lucía\n");
fprintf(archivo, "Carlos\n");
fprintf(archivo, "Marta\n");

fclose(archivo);
return 0;
}

Este código crea un archivo nombres.txt con tres líneas, cada una con un nombre.

Lectura línea a línea con fgets()

Para leer líneas completas de un archivo usamos fgets(). Esta función devuelve un puntero a char. o lo que es lo mismo, un vector de caracteres. A la función se le facilita el puntero a char donde almacenaremos la información (que es el mismo puntero que devolverá la función), el número de bytes que queremos leer y el puntero del archivo donde tenemos que leer).

char *fgets(char *buffer, int tamaño, FILE *archivo);
  • buffer: arreglo donde se almacenará la línea leída.
  • tamaño: número máximo de caracteres a leer.
  • archivo: puntero al archivo.

Ejemplo: Leer línea por línea

#include <stdio.h>

int main() {
FILE *archivo = fopen("nombres.txt", "r");
char linea[100];

if (archivo == NULL) {
printf("No se pudo abrir el archivo para lectura.\n");
return 1;
}

while (fgets(linea, sizeof(linea), archivo) != NULL) {
printf("Línea leída: %s", linea); // No hace falta añadir \n, fgets lo incluye
}

fclose(archivo);
return 0;
}
  • fgets() lee una línea del archivo (hasta que encuentra un salto de línea \n o llega al final del archivo).
  • El bucle while continúa hasta que fgets() devuelve NULL, lo cual indica que se ha llegado al final del archivo o ha ocurrido un error.

Detalles importantes

  1. fgets conserva el salto de línea (\n) si existe en la línea leída.
  2. Asegúrate siempre de definir un tamaño para el buffer suficientemente grande para las líneas esperadas.
  3. Ideal para trabajar con archivos tipo .txt o .csv.

Combinando lectura y procesamiento

Supongamos que tienes un archivo con números (uno por línea) y deseas sumarlos:

Archivo numeros.txt:

10
25
40

Código para sumar:

#include <stdio.h>
#include <stdlib.h>

int main() {
FILE *archivo = fopen("numeros.txt", "r");
char linea[100];
int suma = 0;

if (archivo == NULL) {
printf("No se pudo abrir el archivo.\n");
return 1;
}

while (fgets(linea, sizeof(linea), archivo) != NULL) {
suma += atoi(linea); // convierte la línea a entero
}

printf("La suma total es: %d\n", suma);
fclose(archivo);
return 0;
}

9.4. Modos de apertura de archivos en C/C++

Cuando abrimos un archivo con fopen(), indicamos no solo el nombre del archivo, sino también el modo de apertura, que define lo que queremos hacer con él (leer, escribir, añadir, en texto o binario).

FILE *fopen(const char *nombre_archivo, const char *modo);

El parámetro modo se define con una cadena con alguno de estos valores "r", "w", "rb", etc.

ModoDescripción
"r"Abre un archivo para lectura. El archivo debe existir.
"w"Abre un archivo para escritura. Si ya existe, se borra su contenido. Si no existe, lo crea.
"a"Abre un archivo para añadir contenido al final (append). Si no existe, lo crea.
"r+"Abre un archivo para lectura y escritura. El archivo debe existir.
"w+"Abre un archivo para lectura y escritura, borrando su contenido si ya existe.
"a+"Abre un archivo para lectura y escritura, posicionando el cursor al final. Si no existe, lo crea.

Modos en archivos binarios

Si queremos trabajar con archivos binarios, se añade una "b" al modo:

ModoSignificado
"rb"Leer un archivo binario
"wb"Escribir en un archivo binario (borra contenido previo)
"ab"Añadir contenido a un archivo binario
"r+b" o "rb+"Leer y escribir en binario (archivo debe existir)
"w+b" o "wb+"Leer y escribir, se borra contenido previo
"a+b" o "ab+"Leer y añadir contenido binario

– Abrir un archivo de texto para leer:

FILE *f = fopen("archivo.txt", "r");

Si el archivo no existe, fopen() devolverá NULL.

– Abrir un archivo binario para escritura:

FILE *f = fopen("datos.bin", "wb");

Se crea si no existe. Si ya existe, se borra su contenido.

– Abrir un archivo de texto para añadir contenido:

FILE *f = fopen("registro.txt", "a");

Todo lo que se escriba se añadirá al final del archivo.

Comprobación al abrir archivos

Siempre es conveniente comprobar si el archivo se abrió correctamente:

FILE *f = fopen("algo.txt", "r");
if (f == NULL) {
printf("Error al abrir el archivo.\n");
}

9.5. Comprobación de errores al trabajar con archivos en C/C++

Ya hemos adelantado que cuando trabajamos con archivos, es fundamental comprobar si las operaciones de apertura, lectura o escritura se han realizado correctamente. Esto permite que el programa sea más robusto y evite fallos inesperados como intentar leer un archivo que no existe o escribir en uno que no se pudo abrir.

Comprobación al abrir un archivo

La función fopen() devuelve un puntero a FILE. Si no pudo abrirse el archivo (por ejemplo, porque no existe o no tenemos permisos), devuelve NULL.

FILE *archivo = fopen("datos.txt", "r");
if (archivo == NULL) {
perror("Error al abrir el archivo");
return 1;
}
  • perror() imprime un mensaje de error relacionado con la última operación fallida del sistema.
  • También puedes usar fprintf(stderr, ...) para enviar un mensaje de error personalizado al canal de errores.

Comprobación de lectura y escritura

Para verificar si las operaciones de lectura o escritura han funcionado correctamente, se comprueban los valores devueltos por funciones como fscanf(), fgets(), fread(), fwrite(), etc.

Ejemplo: Verificar lectura con fscanf

int numero;
if (fscanf(archivo, "%d", &numero) != 1) {
printf("Error al leer el número desde el archivo\n");
}

Ejemplo: Verificar escritura con fprintf

if (fprintf(archivo, "Hola mundo\n") < 0) {
printf("Error al escribir en el archivo\n");
}

Detección del fin del archivo

La función feof(FILE *f) se usa para saber si se ha llegado al final del archivo. Es útil cuando leemos dentro de un bucle:

while (!feof(archivo)) {
fscanf(archivo, "%d", &num);
// ...
}

¡¡¡Importante!!! Hay que tener en cuenta que feof() solo se activa después de intentar leer más allá del final, por lo que no siempre es la mejor forma de controlar la lectura.

Verificación de errores de I/O

ferror(FILE *f) devuelve un valor distinto de cero si ha ocurrido un error de entrada/salida (I/O) en el archivo.

if (ferror(archivo)) {
printf("Error de entrada/salida detectado.\n");
}

Limpieza y cierre del archivo

Siempre es importante acordarse de cerrar el archivo con fclose() después de usarlo, esto evita que se produzcan errores o que haya información en el buffer que todavía no haya volcado al archivo que se pierda ante una salida del programa.

if (fclose(archivo) != 0) {
perror("Error al cerrar el archivo");
}

Resumendo

FunciónPropósito
fopen()Abrir archivo
fclose()Cerrar archivo
perror()Mostrar mensaje de error del sistema
feof()Detectar fin de archivo
ferror()Detectar errores de I/O

Recapitulando

En este capítulo hemos aprendido a manejar archivos en C y C++, mecanismo esencial para guardar y recuperar datos de forma persistente más allá del tiempo de ejecución de un programa.

Hemos visto las diferencias entre archivos de texto y archivos binarios, entendiendo cuándo es conveniente utilizar uno u otro. Nos hemos familiarizado con las funciones básicas para trabajar con archivos, como fopen, fscanf, fprintf, fread, fwrite y fclose, que nos permiten abrir, leer, escribir y cerrar archivos correctamente.

Aprendimos a realizar lectura y escritura línea a línea utilizando funciones como fgets() y fputs(), y repasamos los modos de apertura ("r", "w", "a", "rb", "wb", etc.), fundamentales para indicar el tipo de operación que vamos a realizar.

Finalmente, abordamos la comprobación de errores, algo crucial al trabajar con archivos: verificamos si la apertura fue exitosa, si las operaciones de lectura o escritura se realizaron correctamente, y cómo detectar el fin del archivo o errores de entrada/salida mediante funciones como feof(), ferror() y perror().

Vayamos ahora con los ejercicios prácticos.

Ejercicio 1: Contar líneas en un archivo de texto
Enunciado:
Escribe un programa en C que abra un archivo de texto llamado texto.txt, cuente cuántas líneas contiene y muestre el resultado por pantalla. Si el archivo no existe, debe mostrar un mensaje de error.

Código.

#include <stdio.h>

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

    int contadorLineas = 0;
    char buffer[256];

    while (fgets(buffer, sizeof(buffer), archivo) != NULL) {
        contadorLineas++;
    }

    fclose(archivo);

    printf("El archivo tiene %d líneas.\n", contadorLineas);
    return 0;
}

Explicación:
Abrimos el archivo en modo lectura ("r"). Usamos fgets para leer línea a línea hasta llegar al final (NULL). Por cada línea leída, incrementamos un contador. Al finalizar, cerramos el archivo y mostramos el total de líneas.

Ejercicio 2: Copiar contenido de un archivo de texto a otro
Enunciado:
Haz un programa que copie el contenido de un archivo origen.txt a otro archivo llamado copia.txt. El programa debe manejar correctamente la apertura y cierre de ambos archivos y mostrar un mensaje de éxito o error.

Codigo:

#include <stdio.h>

int main() {
FILE *archivoOrigen = fopen("origen.txt", "r");
if (archivoOrigen == NULL) {
printf("Error: no se pudo abrir el archivo origen.\n");
return 1;
}

FILE *archivoDestino = fopen("copia.txt", "w");
if (archivoDestino == NULL) {
printf("Error: no se pudo crear el archivo destino.\n");
fclose(archivoOrigen);
return 1;
}

char caracter;
while ((caracter = fgetc(archivoOrigen)) != EOF) {
fputc(caracter, archivoDestino);
}

fclose(archivoOrigen);
fclose(archivoDestino);

printf("Copia realizada con éxito.\n");
return 0;
}

Explicación:
Abrimos el archivo de origen en modo lectura y el de destino en modo escritura. Leemos carácter a carácter con fgetc y escribimos con fputc hasta llegar al final del archivo (EOF). Luego cerramos ambos archivos y notificamos que la copia fue exitosa.

Ejercicio 3: Guardar números introducidos por el usuario en un archivo binario
Enunciado:
Crea un programa que pida al usuario 5 números enteros, los guarde en un archivo binario llamado numeros.bin y luego lea ese archivo para mostrar los números almacenados.

Código:

#include <stdio.h>

int main() {
    FILE *archivo = fopen("numeros.bin", "wb");
    if (archivo == NULL) {
        printf("No se pudo abrir el archivo para escritura.\n");
        return 1;
    }

    int numeros[5];
    printf("Introduce 5 números enteros:\n");
    for (int i = 0; i < 5; i++) {
        printf("Número %d: ", i + 1);
        scanf("%d", &numeros[i]);
    }

    fwrite(numeros, sizeof(int), 5, archivo);
    fclose(archivo);

    // Lectura del archivo binario
    archivo = fopen("numeros.bin", "rb");
    if (archivo == NULL) {
        printf("No se pudo abrir el archivo para lectura.\n");
        return 1;
    }

    int numerosLeidos[5];
    fread(numerosLeidos, sizeof(int), 5, archivo);
    fclose(archivo);

    printf("Números leídos del archivo:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", numerosLeidos[i]);
    }
    printf("\n");

    return 0;
}

Explicación:
El programa primero abre un archivo binario en modo escritura ("wb"), pide 5 números enteros al usuario y los escribe con fwrite. Luego cierra y vuelve a abrir el archivo en modo lectura binaria ("rb") para leer los números con fread y mostrarlos. Esto ilustra la manipulación básica de archivos binarios.

Logo C++

Bibliografía del tutorial de C/C++.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *