1. Fundamentos de Archivos
Los archivos almacenan datos en el disco duro, permitiendo la persistencia de información incluso cuando el sistema se apaga. Esto contrasta con la memoria RAM, que es volátil.
1.1 Clasificación de Archivos
En programación, los archivos se dividen en archivos de programa (como .c, .obj, .exe) y archivos de datos, que se utilizan para entrada y salida de información durante la ejecución. El nombre de un archivo se compone de la ruta, el nombre principal y la extensión, por ejemplo: c:\proyecto\datos.txt.
Los archivos de datos pueden ser de texto (donde los valores se almacenen como caracteres ASCII) o binarios (con representación directa en memoria). Por ejemplo, el entero 10000 puede guardarse en formato binario o como caracteres ASCII.
1.2 Sistema de Archivos con Buffer
C utiliza un sistema de buffers para operaciones de archivo, donde se asigna un espacio en memoria para cada archivo abierto. Los datos se transfieren entre el programa y el disco mediante este buffer para optimizar el rendimiento. Es crucial cerrar o vaciar el buffer después de las operaciones para evitar problemas de lectura/escritura.
2. Apertura y Cierre de Archivos
2.1 Punteros a Archivos
El tipo FILE es una estructura que contiene información sobre un archivo, como su estado y posición. Se accede mediante punteros, por ejemplo: FILE* puntero_archivo;
2.2 Funciones de Apertura y Cierre
El flujo normal es: abrir archivo -> leer/escribir -> cerrar archivo. Las funciones clave son fopen para abrir y fclose para cerrar.
FILE* fopen(const char* nombre_archivo, const char* modo);``int fclose(FILE* flujo);Los modos de apertura determinan el comportamiento, como lectura ("r"), escritrua ("w"), o adición ("a"), con variantes para archivos binarios y modos de lectura/escritura. Si el archivo no existe, algunos modos lo crean automáticamente.
Ejemplo:
#include <stdio.h>
int main() {
FILE* manejador;
manejador = fopen("registro.txt", "w");
if (manejador != NULL) {
fputs("Ejemplo de operación", manejador);
fclose(manejador);
}
return 0;
}
3. Lectura y Escritura de Archivos
3.1 Operaciones Secuenciales
Funciones comunes incluyen fgetc para leer un carácter, fputc para escribir, fgets y fputs para líneas, y fprintf y fscanf para datos formateados. Estas trabajan con flujos estándar o archivos.
3.2 Acceso Aleatorio
Para posicionamiento flexible, se usan fseek, ftell y rewind.
fseek mueve el puntero del archivo según un origen y desplazamiento:
int fseek(FILE* flujo, long desplazamiento, int origen);
// origenes: SEEK_SET, SEEK_CUR, SEEK_END
Ejemplo de fseek:
#include <stdio.h>
int main() {
FILE* arch;
arch = fopen("ejemplo.bin", "wb");
fputs("Texto inicial", arch);
fseek(arch, 5, SEEK_SET);
fputs("modificado", arch);
fclose(arch);
return 0;
}
ftell devuelve la posición actual del puntero:
long ftell(FILE* flujo);
Ejemplo para obtener tamaño de archivo:
#include <stdio.h>
int main() {
FILE* arch;
long tam;
arch = fopen("datos.dat", "rb");
if (arch != NULL) {
fseek(arch, 0, SEEK_END);
tam = ftell(arch);
fclose(arch);
printf("Tamaño: %ld bytes\n", tam);
}
return 0;
}
rewind reinicia el puntero al inicio:
void rewind(FILE* flujo);
4. Determinación del Fin de Archivo
La función feof verifica si el fin del archivo se alcanzó por error o por llegar al final, pero no debe usarse directamente para controlar bucles de lectura.
Para archivos de texto, se comprueba si fgetc devuelve EOF o fgets deveulve NULL. Para binarios, se compara el número de elementos leídos con el solicitado.
Ejemplo con archivo de texto:
#include <stdio.h>
#include <stdlib.h>
int main() {
int caracter;
FILE* fp = fopen("entrada.txt", "r");
if (!fp) {
perror("Error al abrir");
return EXIT_FAILURE;
}
while ((caracter = fgetc(fp)) != EOF) {
putchar(caracter);
}
if (ferror(fp)) {
puts("Error de E/S");
} else if (feof(fp)) {
puts("Fin de archivo alcanzado");
}
fclose(fp);
return 0;
}
Con archivo binario:
#include <stdio.h>
#define TAMANIO 5
int main() {
double arreglo[TAMANIO] = {1.1, 2.2, 3.3, 4.4, 5.5};
FILE* fp = fopen("binario.bin", "wb");
fwrite(arreglo, sizeof(double), TAMANIO, fp);
fclose(fp);
double leido[TAMANIO];
fp = fopen("binario.bin", "rb");
size_t leidos = fread(leido, sizeof(double), TAMANIO, fp);
if (leidos == TAMANIO) {
for (int i = 0; i < TAMANIO; i++) printf("%f ", leido[i]);
printf("\n");
} else {
if (feof(fp)) printf("Fin inesperado\n");
else if (ferror(fp)) perror("Error de lectura");
}
fclose(fp);
return 0;
}