Está en la página 1de 11

Manejo de Archivos en C. Los datos que hemos tratado hasta el momento han residido en la memoria principal.

Sin embargo, las grandes cantidades de datos se almacenan normalmente en un dispositivo de memoria secundaria. Estas colecciones de datos se conocen como archivos (antiguamente ficheros). Un archivo es un conjunto de datos estructurados en una coleccin de entidades elementales o bsicas denominadas registros que son de igual tipo y constan a su vez de diferentes entidades de nivel ms bajos denominadas campos. Hay dos tipos de archivos, archivos de texto y archivos binarios. Un archivo de texto es una secuencia de caracteres organizadas en lneas terminadas por un carcter de nueva lnea. En estos archivos se pueden almacenar canciones, fuentes de programas, base de datos simples, etc. Los archivos de texto se caracterizan por ser planos, es decir, todas las letras tienen el mismo formato y no hay palabras subrayadas, en negrita, o letras de distinto tamao o ancho. Un archivo binario es una secuencia de bytes que tienen una correspondencia uno a uno con un dispositivo externo. As que no tendr lugar ninguna traduccin de caracteres. Adems, el nmero de bytes escritos (ledos) ser el mismo que los encontrados en el dispositivo externo. Ejemplos de estos archivos son Fotografas, imgenes, texto con formatos, archivos ejecutables (aplicaciones), etc. En c, un archivo es un concepto lgico que puede aplicarse a muchas cosas desde archivos de disco hasta terminales o una impresora. Se asocia una secuencia con un archivo especifico realizando una operacin de apertura. Una vez que el archivo est abierto, la informacin puede ser intercambiada entre este y el programa. Se puede conseguir la entrada y la salida de datos a un archivo a travs del uso de la biblioteca de funciones; C no tiene palabras claves que realicen las operaciones de E/S. La siguiente tabla da un breve resumen de las funciones que se pueden utilizar. Se debe incluir la librera STDIO.H. Observe que la mayora de las funciones comienzan con la letra F, esto es un vestigio del estndar C de Unix. Nombre Funcin fopen() Abre un archivo. fclose() Cierra un archivo. fgets() Lee una cadena de un archivo. fputs() Escribe una cadena en un archivo fseek() Busca un byte especifico de un archivo. fprintf() Escribe una salida con formato en el archivo. fscanf() Lee una entrada con formato desde el archivo. feof() Devuelve cierto si se llega al final del archivo. ferror() Devuelve cierto si se produce un error. rewind() Coloca el localizador de posicin del archivo al principio del mismo. remove() Borra un archivo. fflush() Vaca un archivo.

El puntero a un archivo. El puntero a un archivo es el hilo comn que unifica el sistema de E/S con buffer. Un puntero a un archivo es un puntero a una informacin que define varias cosas sobre l, incluyendo el nombre, el estado y la posicin actual del archivo. En esencia identifica un archivo especifico y utiliza la secuencia asociada para dirigir el funcionamiento de las funciones de E/S con buffer. Un puntero a un archivo es una variable de tipo puntero al tipo FILE que se define en STDIO.H. Un programa necesita utilizar punteros a archivos para leer o escribir en los mismos. Para obtener una variable de este tipo se utiliza una secuencia como esta: FILE *F; Apertura de un archivo. La funcin fopen() abre una secuencia para que pueda ser utilizada y la asocia a un archivo. Su prototipo es: FILE *fopen(const char nombre_archivo, cost charmodo); Donde nombre_archivo es un puntero a una cadena de caracteres que representan un nombre valido del archivo y puede incluir una especificacin del directorio. La cadena a la que apunta modo determina como se abre el archivo. La siguiente tabla muestra los valores permitidos para modo. Modo Significado r Abre un archivo de texto para lectura. w Crea un archivo de texto para escritura. a Abre un archivo de texto para aadir. rb Abre un archivo binario para lectura. wb Crea un archivo binario para escritura. ab Abre un archivo binario para aadir. r+ Abre un archivo de texto para lectura / escritura. w+ Crea un archivo de texto para lectura / escritura. a+ Aade o crea un archivo de texto para lectura / escritura. r+b Abre un archivo binario para lectura / escritura. w+b Crea un archivo binario para lectura / escritura. a+b Aade o crea un archivo binario para lectura / escritura. La funcin fopen() devuelve un puntero a archivo. Un programa nunca debe alterar el valor de ese puntero. Si se produce un error cuando se esta intentando abrir un archivo, fopen() devuelve un puntero nulo. Se puede abrir un archivo bien en modo texto o binario. En la mayora de las implementaciones, en modo texto, la secuencias de retorno de carro / salto de lnea se convierten a caracteres de salto de lnea en lectura. En la escritura, ocurre lo contrario: los caracteres de salto de lnea se convierten en salto de lnea. Estas conversiones no ocurren en archivos binarios. La macro NULL est definida en STDIO.H. Este mtodo detecto cualquier error al abrir un archivo: como por ejemplo disco lleno o protegido contra escritura antes de comenzar a escribir en l. Si se usa fopen() para abrir un archivo para escritura,

entonces cualquier archivo existente con el mismo nombre se borrar y se crea uno nuevo. Si no existe un archivo con el mismo nombre, entonces se crear. Si se quiere aadir al final del archivo entonces debe usar el modo a. Si se usa a y no existe el archivo, se devolver un error. La apertura de un archivo para las operaciones de lectura requiere que exista el archivo. Si no existe, fopen() devolver un error. Finalmente, sus se abre un archivo para las operaciones de leer / escribir, la computadora no lo borrar si existe; sin embargo, si no existe, la computadora lo crear. Cierre de un archivo. La funcin fclose() cierra una secuencia que fue abierta mediante una llamada a fopen(). Escribe toda la informacin que todava se encuentre en el buffer en el disco y realiza un cierre formal del archivo a nivel del sistema operativo. Un error en el cierre de una secuencia puede generar todo tipo de problemas, incluyendo la prdida de datos, destruccin de archivos y posibles errores intermitentes en el programa. El prototipo de esta funcin es: int fclose(FILE *F); Donde F es el puntero al archivo devuelto por la llamada a fopen(). Si se devuelve un valor cero significa que la operacin de cierre ha tenido xito. Generalmente, esta funcin solo falla cuando un disco se ha retirado antes de tiempo o cuando no queda espacio libre en el mismo. Para introducir u obtener datos de un archivo tenemos las siguientes cuatro funciones: fprintf() y fscanf() Estas funciones se comportan exactamente como prinft() y scanf() discutidas anteriormente, excepto que operan sobre archivo. Sus prototipos son: int fprintf(FILE *F, const char *cadena_de_control, .....); int fscanf(FILE *F, const char *cadena_de_control, .....); Donde F es un puntero al archivo devuelto por una llamada a fopen(). fprintf() y fscanf() dirigen sus operaciones de E/S al archivo al que apunta F. Las funciones fgets() y fputs() pueden leer y escribir cadenas a o desde los archivos. Los prototipos de estas funciones son: char *fputs(char *str, FILE *F); char *fgets(char *str, int long, FILE *F); La funcin puts() escribe la cadena a un archivo especifico. La funcin fgets() lee una cadena desde el archivo especificado hasta que lee un carcter de nueva lnea o longitud-1 caracteres. Si se produce un EOF (End of File) la funcin gets retorna un NULL. Funcion feof() Cuando se abre un archivo para entrada binaria, se puede leer un valor entero igual de la marca EOF. Esto podra hacer que la rutina de lectura indicase una condicin de fin de archivo an cuando el fin fsico del mismo no se haya alcanzado. Para resolver este problema, C incluye la funcin feof(), que determina cuando se ha alcanzado el fin del archivo leyendo datos binarios. La funcin tiene el siguiente prototipo: int feof(FILE *F);

Su prototipo se encuentra en STDIO.H. Devuelve cierto si se ha alcanzado el final del archivo, en cualquier otro caso, 0. Por supuesto, se puede aplicar este mtodo a archivos de texto tambin. Ahora bien para el ejemplo anterior usted incluir los datos de la forma: Nombre del alumno1 nota Nombre del alumno2 nota ..... Algunas veces usted necesitara manipular por separado el nombre del alumno y su nota, para esto es necesario separarlo en campos. Se puede realizar introduciendo caracteres elimitadores entre campo y campo, por ejemplo: fprinft(C,%s;%d \n,nombre,cal); Esto generara un archivo de tipo: Nombre del alumno1;nota Nombre del alumno2;nota ..... La funcin rewind() inicializa el indicador de posicin, al principio del archivo, indicado por su argumento. Su prototipo es: void rewind (FILE *F); Donde F es un puntero a un archivo vlido. Esta funcin se encuentra en STDIO.H La funcin ferror() determina si se ha producido en error en una operacin sobre un archivo. Su prototipo es: int ferror(FILE *F); Donde F es un puntero a un archivo vlido. Devuelve cierto si se ha producido un error durante la ultima operacin sobre el archivo. En caso contrario, devuelve falso. Debido a que cada operacin sobre el archivo actualiza la condicin de error, se debe llamar a ferror() inmediatamente despus de la operacin de este tipo; si no se ase as, el error puede perderse. Esta funcin se encuentra en STDIO.H La funcin remove() borra el archivo especificado. Su prototipo es el siguiente:int remove(char *nombre_archivo); Devuelve cero si tiene xito. Si no un valor distinto de cero. La funcin fflush() escribe todos los datos almacenados en el buffer sobre el archivo asociado con un apuntador. Su prototipo es: int fflush(FILE *F); Si se llama esta funcin con un puntero nulo se vacian los buffers de todos los archivos abiertos. Esta funcin devuelve cero si tiene xito, en otro caso, devuelve EOF. FICHEROS EN LENGUAJE C Los ficheros, en contraposicin con las estructuras de datos vistas hasta ahora (variables simples, vectores, registros, etc.), son estructuras de datos almacenadas en memoria secundaria. Para utilizar la informacin en memoria principal se emplea fundamentalmente la instruccin de asignacin; sin embargo, para guardar o

recuperar informacin de un fichero es necesario realizar una serie de operaciones que describiremos en este apartado. El formato de declaracin de un fichero es el siguiente: FILE * nom_ var_fich; En otros lenguajes la declaracin del fichero determina el tipo de datos que se van a almacenar en l. En C la filosofa es distinta, todos los ficheros almacenan bytes y es cuando se realiza la apertura y la escritura cuando se decide cmo y qu se almacena en el mismo; durante la declaracin del fichero no se hace ninguna distincin sobre el tipo del mismo. En la operacin de apertura se puede decidir si el fichero va a ser de texto o binario, los primeros sirven para almacenar caracteres, los segundos para almacenar cualquier tipo de dato. Si deseamos leer un fichero como el autoexec.bat utilizaremos un fichero de texto, si queremos leer y escribir registros (struct) usaremos un fichero binario. APERTURA Y CIERRE DE FICHEROS Hasta ahora, para obtener y almacenar datos de una estructura de datos bastaba con realizar asignaciones a la misma. Para utilizar los ficheros el procedimiento es distinto. Antes de usar un fichero es necesario realizar una operacin de apertura del mismo; posteriormente, si se desea almacenar datos en l hay que realizar una operacin de escritura y si se quiere obtener datos de l es necesario hacer una operacin de lectura. Cuando ya no se quiera utilizar el fichero se realiza una operacin de cierre del mismo para liberar parte de la memoria principal que pueda estar ocupando (aunque el fichero en s est almacenado en memoria secundaria, mientras est abierto ocupa tambin memoria principal). La instruccin ms habitual para abrir un fichero es : FILE * fichero; fichero = fopen ( nombre-fichero, modo); La funcin fopen devuelve un puntero a un fichero que se asigna a una variable de tipo fichero. Si existe algn tipo de error al realizar la operacin, por ejemplo, porque se desee abrir para leerlo y ste no exista, devuelve el valor NULL. El nombre-fichero ser una cadena de caracteres que contenga el nombre (y en su caso la ruta de acceso) del fichero tal y como aparece para el sistema operativo. El modo es una cadena de caracteres que indica el tipo del fichero (Texto o Binario) y el uso que se va ha hacer de l lectura, escritura, aadir datos al final, etc. Los modos disponibles son: r abre un fichero para lectura. Si el fichero no existe devuelve error. w abre un fichero para escritura. Si el fichero no existe se crea, si el fichero existe se destruye y se crea uno nuevo. a abre un fichero para aadir datos al final del mismo. Si no existe se crea. + smbolo utilizado para abrir el fichero para lectura y escritura. b el fichero es de tipo binario.

t el fichero es de tipo texto. Si no se pone ni b ni t el fichero es de texto. Los modos anteriores se combinan para conseguir abrir el fichero en el modo adecuado. Por ejemplo, para abrir un fichero binario ya existente para lectura y escritura el modo ser "rb+ "; si el fichero no existe, o aun existiendo se desea crear, el modo ser " wb+ ". Si deseamos aadir datos al final de un fichero de texto bastar con poner "a", etc. La forma habitual de utilizar la instruccin fopen es dentro de una sentencia condicional que permita conocer si se ha producido o no error en la apertura, por ejemplo: FlLE *fich; if ((fich = fopen("nomfich.dat", "r")) == NULL) { /* control del error de apertura * / printf ( " Error en la apertura. Es posible que el fichero no exista \n "); } El resultado de fopen se almacena en la variable fich y despus se compara fich con NULL para saber si se ha producido algn error. Toda la operacin se puede realizar en la misma instruccin, tal y como aparece en el ejemplo. Cuando se termine el tratamiento del fichero hay que cerrarlo; si la apertura se hizo con fopen el cierre se har con fclose (fich); Para utilizar las instrucciones de manejo de ficheros que veremos en esta unidad es necesario incluir la librera <stdio.h>. LECTURA Y ESCRITURA EN FICHEROS Para almacenar datos en un fichero es necesario realizar una operacin de escritura, de igual forma que para obtener datos hay que efectuar una operacin de lectura. En C existen muchas y variadas operaciones para leer y escribir en un fichero; entre ellas tenemos: fread -fwrite, fgetc -fputc, fgets - fputs, fscanf -fprintf. Es aconsejable utilizarlas por parejas; es decir, si se escribe con fwrite se debe leer con fread.
Lectura y escritura de bloques ( fread fwrite )

Para leer y escribir en ficheros que no sean de texto las operaciones que se deben utilizar son fread y fwrite. El formato de escritura en bloque es el siguiente: fwrite (direcc_dato, tamao_dato, numero_datos, punt_fichero); Escribe tantos datos como indique numero de datos en el fichero, tomando los datos a partir de la direccin del dato. Los datos tienen que tener tantos bytes como especifique tamao. La funcin fwrite devuelve el nmero de elementos escritos, este valor debe coincidir con numero de datos. Para calcular el tamao en bytes de un dato o un tipo de dato se suele utilizar la funcin sizeof (dato) o sizeof (tipo-de-dato); Por ejemplo: int i, v[3]; sizeof (i) dara lo mismo que sizeof (int) sizeof (v) dara 3 veces el resultado de sizeof (V[1]) Por ejemplo: FlLE *f;

int v[6], elem_escritos, num; f = fopen (datos.cht ", "wb "); /* Para escribir los 3 ltimos elementos de v (el 2, el 3 y el 4) */ elem-escritos = fwrite (&v[2], sizeof(int), 3, f ); /* Para escribir el primer elemento de v, valen las 2 instrucciones siguientes */ fwrite (v, sizeof (int), 1, f ); fwrite (&v[0], sizeof(int), 1, f ); /* Para escribir un entero valen las dos siguientes */ fwrite (&num, sizeof(int), 1, f); fwrite (&num, sizeof(num), 1, f); La sentencia de lectura de bloque es la siguiente: fread (direcc_dato, tamao_dato, numero_datos,punt_fichero); Lee tantos datos como indique numero de datos del fichero, colocando los datos ledos a partir de la direccin del dato. Los datos tienen que tener tantos bytes como especifique tamao del dato. La funcin fread devuelve el nmero de elementos ledos, y el valor devuelto debe coincidir con numero de datos. Ejemplos: f = fopen (datos.dat ", "rb "); elem-escritos = fread (&v[2], sizeof(int), 3, f); fread (v, sizeof(int), 1, f); fread (&V[0], sizeof(int), 1, f); fread (&num, sizeof(int), 1, f); fread (&num, sizeof(num), 1, f);
LECTURA Y ESCRITURA FORMATEADA DE TEXTO ( fscanf fprintf )

Las instrucciones scanf y printf utilizadas normalmente para lecturas y escrituras de teclado y pantalla tienen sus correspondientes funciones para el manejo de ficheros: fscanf y fprintf. La nica diferencia con las anteriores es la necesidad de dar como primer argumento el fichero en el que leemos o escribimos. Para que lo escrito con fprintf pueda ser correctamente ledo con fscanf es conveniente que el formato en el que se indican los tipos de datos que se van a leer o escribir sean similares para ambas instrucciones, que los tipos de datos estn separados, por ejemplo, por un blanco y que tengan un fin de lnea al final. Por ejemplo, los siguientes pares de instrucciones de lectura y escritura seran compatibles: int num; char car, cad [10] ; FILE *f. /* apertura del fichero */ ..... ..... fscanf (f, "%d %c %s ", &num, &car, cad); fprintf ( f, "%d %c %s \n ", num, car, cad);

fscanf (f, "%s %c %d ", cad, &car, &num); fprintf (f, "%s %c %d \n ", cad, car, num);
Lectura y escritura de caracteres ( fgetc fputc ) y cadenas ( fgets fputs )

Los formatos de las instrucciones de lectura y escritura de caracteres y cadenas son: carcter_leido = fgetc (fichero); fgetc lee un carcter del fichero, el carcter ledo se almacenar en carcter ledo. Cuando se llega al final del fichero devuelve EOF. fputc (car, fichero);. fputc escribe el carcter car en el fichero. Devuelve el carcter escrito o EOF en caso de error. fgets (cadena_leida, num_caracteres, fichero);Lee num_caracteres del fichero y los almacena en cadena_leida colocando el carcter de fin de cadena '\0' en la posicin num_caracteres de la cadena leda. Por ejemplo: FlLE *f; char cad[5]; fgets (cad, 5, f); almacena en cad la cadena " Buen " si se lee la lnea " Buenas tardes " del fichero f. Si se realizan dos lecturas, en la segunda se almacena en cad la cadena as t ". fputs (cadena_escribir, fichero); escribe la cadena en el fichero. Por ejemplo:. fputs (cad, f);. Ejemplo : Copiar un fichero de texto en otro. #include <stdio.h> main ( ) { FILE *fin *fout; char c, x; if (((fin = fopen(DATOSIN.DAT", rt")) == NULL) || ((fout = fopen(DATOSOUT.DAT" , wt")) == NULL)) { if (fout ! = NULL) fclose (fout) ; if (fin ! = NULL) fclose (fin) ; printf (Error en la apertura de ficheros de salida \n ); return 1; } c = fgetc(fin); while (c != EOF) { x = fputc (c, fout); if (x! = c) printf ("Error de escritura"); c = fgetc(fin); } fclose (fin); fclose (fout); return 0; } RECORRIDO DE UN FICHERO SECUENCIAL (feof)

Las lecturas y escrituras en un fichero se realizan en la posicin en la que se encuentra el puntero del fichero. Al abrir el fichero el puntero est antes del primer dato del mismo. Cada vez que se realiza una operacin de lectura o escritura el puntero se mueve hasta apuntar al dato y despus lo lee o escribe. Por ejemplo, en un fichero f con dos datos (O y 1) al abrir el fichero tendramos la siguiente situacin: Posicin del puntero | puntero Datos | | 0 | | 1 | eof

Si realizamos la operacin fread(&i, sizeof(int), 1, f); en la variable i tendremos almacenado el 0 y la situacin despus de la lectura ser: Posicin del puntero |puntero | Datos | 0 | 1 | eof Para leer todos los datos de un fichero basta con realizar lecturas sucesivas hasta que se lee el final del fichero. En un ejemplo anterior hemos visto cmo se puede detectar el final del fichero teniendo en cuenta el dato ledo (leer hasta que fgetc( ) devuelva EOF). Esta operacin es correcta, pero es ms habitual utilizar una funcin de C que nos indica cundo se ha ledo el ltimo dato: feof (fichero) devuelve un valor distinto de 0 cuando se ha alcanzado el final del fichero. Ejemplo: Escribir cinco registros en un fichero y leerlo posteriormente. Solucin: #include <stdio.h> struct t_reg { int num; char cad[10]; char car; }; int crear_fichero () { FILE *fich; int i, er_dev = 0; struct t_reg r; if ((fich = fopen(fichreg.dat", wb")) == NULL) { printf ("Error en apertura del fichero para escritura\n"); er_dev = 1; } else { for (i = 0; i < 5; i + + ) { r.num = i; r.car=a+1; printf("D un nombre: "); gets(r.cad); fwrite(&r, sizeof(r), 1, fich); }

fclose (fich); } return er_dev; } int Ieer_fichero () { FILE *fich; struct t-reg r; int er_dev = 0; if ((fich = fopen(fichreg.dat", rb")) == NULL) { printf ( Error en apertura del fichero para lectura \n ); er_ dev = 1. } else { fread (&r, sizeof(r), 1, fich); while (! feof(fich)) { printf ("%d: %s: %c\n" , r.num, r.cad, r.car); fread (&r, sizeof(r), 1, fich); } fclose (fich); } return er_dev; } int main(void) { int error; error = crear_fichero(); if (!error) Ieer_fichero(); } ACCESO DIRECTO A LOS DATOS (fseek) Cuando se lee un dato de un fichero y despus el que est a continuacin de l, y as sucesivamente, se dice que se est realizando una lectura secuencial del mismo. Cuando se puede acceder a cualquier dato de un fichero sin tener que pasar por anteriores se est realizando un acceso directo a los datos. La funcin que permite situarse en un determinado dato del fichero es: fseek (fichero, posicion, origen); que coloca el puntero del fichero a tantos bytes del origen como indica posicin contando a partir del origen sealado. Los orgenes posibles son: SEEK_SET o 0 : principio del fichero. SEEK_CUR o 1 : posicin actual. SEEK_END o 2 : final del fichero. fseek devuelve 0 si no ha habido ningn error. Por ejemplo, en un fichero que almacene nmeros enteros la instruccin fseek (f, 0, SEEK-SET); colocar el puntero al principio del fichero. fseek (f, 3*sizeof(int), SEEK-CUR); colocar el puntero 3 posiciones ms all de la posicin actual del puntero. Para saber cul es la posicin en

la que est el puntero del fichero C proporciona la funcin siguiente: ftell (fich); que devuelve la posicin actual en bytes del puntero del fichero con respecto al principio del mismo.

También podría gustarte