MANEJO DE ARCHIVOS EN C

Para abrir un archivo en forma binaria y para lectura, haremos lo siguiente. ... caso particular TODOS los registros lógicos poseen la misma extensión en bytes.
373KB Größe 11 Downloads 115 vistas
Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2014 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. -----------------------------------------------------------------------------------------------------------------------

MANEJO DE ARCHIVOS EN C. Archivos binarios. En los archivos de texto teníamos registros formados por una cierta cantidad de caracteres alfanuméricos y finalizados en el par CR-LF (o sea Carriadge Return y Line Feed), brindando el lenguaje un conjunto de funciones para el manejo cómodo de dichos archivos. En los archivos binarios el concepto de dato se pierde, pues ahora sólo tenemos un flujo de bytes hacia y desde un dispositivo de almacenamiento. Ello no quiere decir que no podamos manejar perfectamente archivos de texto, sólo que con un poco más de trabajo. Pero se puede. Para abrir un archivo en forma binaria y para lectura, haremos lo siguiente. if((Archi=fopen(NombArchi,"rb")==NULL) { cprintf("No pudo abrir el archivo fuente"); getch( ); return; } y para abrirlo en modo escritura: if((Archi=fopen(NombArchi,"wb")==NULL) { cprintf("No pudo abrir el archivo fuente"); getch( ); return; } Siempre es conveniente chequear si la operación fue exitosa. También es válido aquí todo lo dicho en el modo texto en cuanto a la actualización de archivos, salvo que ahora va la letra 'b' y no la 't'. Por ejemplo: ab rb+ wb+ etc. Existen dos funciones claves para el manejo de archivos binarios: int fread(void *Donde_Guarda, int Tam_Bloque, int NroDeBloques, FILE *stream) int fwrite(void *Desde_Saca, int Tam_Bloque, int NroDeBloques, FILE *stream) Si estamos leyendo - fread( ) - el primer parámetro indica la dirección a partir de la cual se almacenarán los bytes extraídos del archivo. En cambio si estamos escribiendo -fwrite( ) indicará la dirección desde dónde se extraerán los datos a grabar en el archivo.

CLASE DE TEORÍA Nro 6

Página 1 de 29

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2014 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------El elemento de programa que recibe o emite datos puede ser desde una variable simple hasta arreglos y estructuras complejas de datos. Estas dos instrucciones reciben o emiten paquetes de bytes de la siguiente manera: tamaño de cada bloque de un cantidad de bloques Lo más cómodo es especificar que el tamaño de bloque sea siempre igual a 1, y el número de bloques la cantidad de bytes que deseamos movilizar. Un ejemplo aclarará bien esta idea: const DIM = ..... typedef struct TDatos { ............. }; TDato Datos[DIM]; . . . for(i=0;iEstado )!=EOF) { utiliza los trucos ya explicados en la clase pasada para poder leer correctamente archivos de texto con formatos y extrae, o asigna, a variables individuales del tipo adecuado. Estas variables son, obviamente, cada uno de los miembros de la estructura que constituirá cada registro lógico del archivo binario (todos de la misma longitud). La instrucción: fwrite(Datos,1,sizeof(TDatos),Destino); es la encargada de guardar cada registro en el archivo binario. Aquí se ve mucho mejor lo que dijimos en un comienzo: tomar como tamaño de bloques 1 byte y guardar la estructura completa: sizeof(TDatos).

Como segunda parte de este programa, mostraremos otro en el cual, ya grabado el archivo binario, procedemos a leerlo aleatoriamente, o sea saltando a registros remotos:

/* --- TALLER DE LENGUAJES I 2014 Leer aleatoriamente un archivo (binario Lista de propiedades_bin).cpp Este programa lee de manera aleatoria 4 registros de un archivo binario. Para ello utiliza la función fseek( ) debiendo tener muy en cuenta que los desplazamientos son en CANTIDAD DE BYTES y no solamente en cantidad de registros. Note la sintaxis: fseek(Fuente,NroReg[ i ]*sizeof(TDatos),SEEK_SET) donde el punto de referencia elegido es desde el origen: SEEK_SET --> a partir del origen del archivo. SEEK_CUR --> a partir de la posición actual del puntero. SEEK_END --> a partir del final del archivo. ------------------------------------------------------------------------------------------------------------- */

CLASE DE TEORÍA Nro 6

Página 18 de 29

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2014 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------#include #include #include #include #include typedef struct TDatos {

int Codigo; char Domicilio[30]; float SupCub; char Estado[16];

} TDatos; // --------------------------------------------------------------------------------------------------------------------void main( ) { TDatos *Datos; FILE *Fuente; char NombFuente[128] = "D:\\DISCO F\\Leng214\\Lista de propiedades.bin"; int NroReg[4] = { 3,10,28,0 }; // ... registros a leer aleatoriamente. int i; clrscr( ); if((Datos=(TDatos *)malloc(sizeof(TDatos)))==NULL){ cprintf("NO PUDO RESERVAR MEMORIA DINAMICA"); getch(); return; } if((Fuente=fopen(NombFuente,"rb"))==NULL) { cprintf("NO PUDO ABRIR ARCHIVO FUENTE"); getch(); return; } for(i=0;iCodigo); cprintf("Domicilio : %s\r\n", Datos->Domicilio); cprintf("SupCubierta : %6.2f\r\n", Datos->SupCub); cprintf("Estado : %s\r\n", Datos->Estado); cprintf("---------------------------------------------------------\r\n"); // if(getch()==27) break; } CLASE DE TEORÍA Nro 6

Página 19 de 29

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2014 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------fclose(Fuente); getch(); } La instrucción: fseek(Fuente,NroReg[i]*sizeof(TDatos),SEEK_SET); encargada de posicionar el puntero de archivo en una posición dada, realiza saltos en cantidades de bytes. Es por eso que si se desea ir al registro 4, en realidad tendríamos que hacer 4.sizeof(TDatos) de lo contrario sólo aterrizaríamos en el byte nro 4. En cuanto a la lectura de cada registro: fread(Datos,1,sizeof(TDatos),Fuente); debe extraerse el paquete completo equivalente a la estructura: sizeof(TDatos).

Otro ejemplo de aplicación de archivos binarios.

/* --- TALLER DE LENGUAJES I 2014 Archivo binario de números primos.cpp Este programa genera una tabla de números primos entre 2 y 32000 y los va almacenando en un archivo binario con la función putw( ). --------------------------------------------------------------------------------------------------------- */

#include #include #include #include

void main() { int Total = 32000; int i,j; int EsPrimo; FILE *Destino; char NombDestino[128] = "D:\\DISCO F\\Leng214\\Tabla de Primos.bin"; clrscr();

CLASE DE TEORÍA Nro 6

Página 20 de 29

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2014 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------if((Destino=fopen(NombDestino,"wb"))==NULL) { cprintf("NO PUDO CREAR ARCHIVO DESTINO"); getch(); return; }

for(i=2;i