MANEJO DE ARCHIVOS EN C.

Un flujo o secuencia de bytes hacia un dispositivo de almacenamiento, en donde el con- cepto de dato desparece. Esto sería mirando desde el hardware: el SO ...
427KB Größe 8 Downloads 96 vistas
Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2015 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. -----------------------------------------------------------------------------------------------------------------------

MANEJO DE ARCHIVOS EN C. Un archivo puede definirse en forma lógica diciendo que:

Es un grupo de datos estructurados que son almacenados en algún medio y pueden ser utilizados por las aplicaciones.

Las aplicaciones conocidas como Word, PowerPoint, Excel, etc. generan sus propios archivos a los cuales le anexan una extensión que los caracteriza. Por ejemplo: .docx .xlsx .pptx .txt .psd .mp3

Archivos de Word. Archivos de Excel. Presentación Power. Cuaderno de notas. Photoshop. Reproductor de Windows / AIMP / Winamp / etc.

Estos archivos deben ser utilizados exclusivamente por la aplicación que los generó. Sin embargo la mayoría de las aplicaciones pueden manejar archivos de imágenes: .jpg .bmp .tif etc. Un documento de Word puede insertar una imagen .jpg. Una planilla en Excel puede importar un archivo de texto con formato. etc. Desde un punto de vista más básico un archivo es: Un flujo o secuencia de bytes hacia un dispositivo de almacenamiento, en donde el concepto de dato desparece. Esto sería mirando desde el hardware: el SO recibe un pedido de guardar o leer una cierta cantidad de bytes, los cuales carecen de todo significado para él. El encargado de verter esos bytes en el molde adecuado a fin de que tenga algún sentido para el usuario, es la Aplicación que lo solicitó. Ocurre algo similar a cuando generábamos una reserva de memoria (una cierta cantidad de bytes) y almacenábamos algo allí. Si accedíamos a esa reserva con un puntero "tipificado" como una estructura, los bytes adquirían automáticamente un sentido perfectamente lógico al ubicarse en cada miembro de la estructura.

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2015 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------También podemos decir que los archivos pueden ser: EJECUTABLES. NO-EJECUTABLES. Los ejecutables "corren" por sí mismo. Los no-ejecutables requieren de un programa o aplicación asociada: por ejemplo una imagen requiere de un "visualizador" como el de Windows. Un archivo de sonido .mp3 o .wav requiere de un "reproductor" de música como el Winamp, etc. El sistema de entrada/salida de C puede agruparse en 2 categorías fundamentales: Entrada / Salida por Consola. Entrada / Salida de archivos con buffers. En los archivos con buffers se utiliza un banco de memoria intermedia, pudiéndose esquematizar de la siguiente manera:

Funciones de Entrada/Salida

Memoria Intermedia (Buffer )

Envío Recepción

El buffer intermedio puede descargarse de dos maneras diferentes:  

Con instrucciones específicas. Al finalizar el programa.

IMPORTANTE: Los quiebres intermedios del programa (finalización anormal, por ejemplo si se cumple determinada condición), pueden provocar pérdida de información. Por eso debemos asegurarnos de completar el envío de lo que haya podido quedar en el buffer "antes" de finalizar.

En realidad las funciones de consola son obtenidas a partir de funciones más generales del sistema de archivos con buffer (aunque para el principiante resulte más conveniente estudiarlas por separado como si se tratase de cosas bien diferenciadas). Si bien cada dispositivo es diferente, el sistema de archivos con buffer liga a cada uno de ellos en un dispositivo lógico llamado flujo, resultando que todos los flujos son similares en su comportamiento. Así por ejemplo, funciones que escriben en un archivo en disco, pueden también escribir en consola.

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2015 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------Por ejemplo: fprintf ( stdout, .... ); fprintf ( stdprn, .... ); fprintf ( FILE *, .... );

El puntero a archivo. El lazo común que mantiene al sistema de archivos con buffer unido, es el puntero a archivo: FILE *fp Se trata de un apuntador a una estructura que define información sobre el archivo. Su definición se halla en la librería stdio.h y es la siguiente: typedef struct { short level; unsigned char unsigned char short unsigned char unsigned char unsigned short

flags; fd; hold; buffsize; *buffer *curp; istemp; token;

// ... Nivel de llenado. // ... Estado del archivo. // .... Descriptor de archivo. // .... ungetchsi no hay buff. // ....Tamaño del buffer. // .... Puntero a buffer. // .... Puntero al próx elemento. // .... Indic. de archivo temporal. // .... P/chequeos de validación.

} FILE;

Apertura de un archivo. Ninguna operación puede realizarse sobre un archivo si antes no ha sido abierto. La siguiente instrucción:

FILE *fp; fp=fopen(NombArchivo,"modo_de_apertura");

El prototipo completo sería: FILE *fopen(const char *NombArchivo, const char *Modo)

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2015 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------Si la operación fue exitosa, retorna una dirección válida, caso contrario retorna NULL. Lo correcto sería aprovechar esta circunstancia para mejorar nuestro código: if((fp=fopen(NombArchivo,Modo))==NULL) { cprintf("NO PUDO ABRIR EL ARCHIVO"); getch( ); exit(1); }

Los modos de apertura. El modo de apertura indica los tipos de operaciones que pueden realizarse sobre el mismo: rt wt rb at

wb ab rt+

rb+ wb+ ab+

Abre archivo de texto para lectura. Crea un archivo de texto para escritura. Abre archivo binario para lectura. Actualizar archivo de texto: Agrega datos al final del mismo. Si no existe el archivo lo crea. Crea un archivo binario para escritura. Actualiza un archivo binario. Abre un archivo de texto para lectura/escritura: Si existe no se borra. Si no existe, lo crea. Abre un archivo binario para lectura/escritura. Crea un archivo binario para lectura/escritura. Abre un archivo binario para actualización.

IMPORTANTE:  

El puntero fp no debe ser alterado por el programa. Si el archivo se abre en modo w y el mismo ya existía, resulta eliminado. Si no existía es creado.

Sería muy útil elaborar una función que permita determinar la existencia de un archivo: int FileExiste (char *NombFile) { FILE *Aux; if((Aux=fopen(NombFile,"rb"))==NULL) return(0); fclose(Aux); return(1); }

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2015 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. -----------------------------------------------------------------------------------------------------------------------

Cierre de un archivo. int fclose(FILE *fp)  

Vuelca el contenido del buffer hacia el medio de almacenamiento. Se desliga del archivo y libera el buffer que tuviera asignado.

 

Si la operación fue exitosa, retorna 0. En caso de fallo retorna un código distinto de 0.

Cuando se intenta cerrar un archivo que ya ha sido cerrado, se genera un error. La operación de cierre resulta muy importante, sobre todo en los procesos de escritura, puesto que en el sistema de archivos con buffer las transferencias a disco se realizan bajo las siguientes circunstancias:   

El buffer se halla completamente lleno. Se ha llevado a cabo una operación de volcado con fflush( ). Se ha realizado el cierre del archivo.

Esto indica que si al finalizar las operaciones de escritura el buffer se hallaba parcialmente lleno, su contenido no será transferido al disco, a menos que el archivo sea cerrado (o se ejecute fflush( ) ).

Archivos de texto. En el caso particular de los archivos de texto, que es lo que nos interesa en este momento, nos centraremos exclusivamente en los textos puros, generados por ejemplo por el Cuaderno de Notas o los Editores de algún lenguaje de programación. Las características fundamentales de estos archivos son:    

Sólo pueden almacenar caracteres. Están formados por registros que pueden tener cualquier longitud. Cada registro finaliza en uno o dos caracteres de control: CR y LF. No se pueden acceder aleatoriamente.

C dispone de varias funciones para lectura de un archivo de texto:   

Se pude leer línea a línea sin formato. Línea a línea con formato. Caracter a caracter.

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2015 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------IMPORTANTE: Hasta este momento hemos estado acostumbrados a que una cadena de caracteres siempre finaliza con '\0'. Pues en un archivo de texto esta situación no se da, ya que hemos dicho que finalizan en el par CR+LF.

Lectura sin formato de un archivo de texto. Analicemos el primer caso, el más simple: leer línea a línea sin formato. Para ello utilicemos primero la función fgets( ) - obtener una cadena desde un archivo. Su prototipo es: char *fgets(char *Destino,total_a_leer,FILE *Fuente); Va leyendo caracteres desde el archivo hasta que ocurre una de dos situaciones:  

Cuando alcanza (total_a_leer - 1) caracteres. Cuando se topa con un caracter LF (ASCII=10),

fgets( ) saltea el CR, retiene el caracter LF al final de Destino, y agrega un byte null a fin de que la cadena finalice de la forma acostumbrada. En definitiva, la cadena tiene ahora un caracter de más. La cadena Destino quedaría como:

T E X T O L E I D O LF \0

Esto quiere decir que, si deseamos obtener una cadena como la conocíamos, debemos hacer: Destino[strlen(Destino)-1] = '\0' En caso de éxito, fgets( ) un puntero a Destino. En caso de fallo o final de archivo, regresa una dirección NULL. Esta función tiene una hermana complementaria que es la función fputs( ) cuyo formato completo sería: int fputs(char *Cadena,FILE *Destino); Copia la cadena finalizada en null hacia el archivo Destino. Agrega un caracter CR y el LF que conservó fgets( ), y el caracter de terminación null no es copiado. En caso de éxito retorna el número de caracteres copiados. En caso de error regresa EOF. Lo interesante de esta función es que, al realizar el proceso de escritura agrega nuevamente el caracter CR que fgets( ) había excluido, quedando nuevamente la cadena en disco con el par CR+LF.

Carrera de Programador Universitario & Licenciatura en Informática TALLER DE LENGUAJES I 2015 - Dictado: Ing. Juan M. Conti FACET de la Universidad Nacional de Tucumán. ----------------------------------------------------------------------------------------------------------------------Seguramente ambas funciones han sido pensadas para trabajar juntas. Para ilustrar lo dicho, se muestra el siguiente programa; #include #include #include #include // ---------------------------------------------------------------void main() { FILE *Fuente; FILE *Destino; char NombFuente[128] = "D:\\DISCO F\\Leng214\\TextoViernes.txt"; char NombDestino[128] = "D:\\DISCO F\\Leng214\\CopiaTextoViernes.txt"; char Linea[128]; int i; clrscr(); if((Fuente=fopen(NombFuente,"rt"))==NULL){ cprintf("NO PUDO ABRIR ARCHIVO FUENTE"); getch(); return; } if((Destino=fopen(NombDestino,"wt"))==NULL){ cprintf("NO PUDO CREAR ARCHIVO DESTINO"); fclose(Fuente); getch(); return; } while(fgets(Linea,127,Fuente)!=NULL){ for(i=0;i