Entrada y Salida Por Archivos
Entrada y Salida Por Archivos
Entrada y Salida Por Archivos
Ficheros en C
Entradas y salidas con ficheros
11/08/2009 [DEPARTEMENTO DE COMPUTACION FACULTAD DE CIENCIAS Y TECNOLOGIA] .
Pgina 1
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len
1. Flujos:
Un flujo (stream) es una abstraccin que se refiere a un flujo o corriente de datos que fluyen entre un origen o fuente (productor ) y un destino o (consumidor). Entre el origen y el destino debe existir una conexin o canal (pipe) por la que circulan los datos. La apertura de un archivo supone establecer la conexin del programa con el dispositivo que contiene el archivo, por el canal que comunica el archivo con el programa van a fluir la secuencia de datos. Hay tres flujos o canales abiertos automticamente cuando se ejecuta un programa. extern FILE *stdin extern FILE * stdout. Extern FILE * stderr. Estas tres variables se inicializan al comenzar la ejecucin del programa para admitir secuencias de caracteres, en modo texto su contenido es: stdin asocia al teclado(entrada estndar) stdout asocia a la pantalla (salida estndar) stderr asocia a la salida de mensajes de error(pantalla). Ejemplo: Cuando ejecutamos printf( Estamos en las Olimpiadas 2008); esto se escribe en la pantalla (stdout) Si queremos leer una variables a travs del teclado (stdin) usamos scanf(%d,&x); El acceso a los archivos se hace con un buffer intermedio. Podemos pensar en l como un array donde se almacena los datos que van al archivo, o que salen del archivo; el buffer se vuelca cuando de una forma u otra se da la orden de vaciarlo. Ejemplo cuando estamos llamamos a una funcin para leer cadenas de carcter la funcin lee cuantos caracteres quepan en el buffer. Despus se obtiene la cadena del buffer, este queda vacio y una llamada posterior a la funcin obtiene la siguiente cadena. El lenguaje C trabaja con archivos con buffer, y est diseado para acceder a muchos dispositivos como una secuencia, pudiendo haber secuencias de caracteres (texto) y secuencia binarias(0 y1).
2. Puntero FILE.
Los archivos se guardan en dispositivos externos como Disco duro, cintas , Pendrive, etc. Y tienen un nombre y unas caractersticas. En el programa el archivo tiene un nombre interno que es un puntero a una estructura predefinida ( puntero a archivo). Esta estructura contiene informacin sobre el archivo, tal como la direccin del buffer, el ltimo carcter que sali del buffer, modo de apertura, etc. El identificador de esta estructura es FILE y se encuentra declarado en el fichero de cabecera stdio.h Typedef struct { short level; unsigned flags; char fd; unsigned char hold; short bsize; unsigned char * buffer, *curp;
Pgina 2
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len unsigned istemp; short token; } FILE; Esta estructura puede cambiar de un compilador a otro, pero al programador solo le interesa su uso como estructura FILE. Lo que nos indica que para cada fichero que abramos tenemos que definir FILE *p;(o sea un puntero a la estructura FILE). Ejemplo: FILE *pf; Tambin la entrada estndar y salida estndar estn asociada a esta estructura FILE * stdin,*stdout // estas estn ya definida en stdio.h .
3. Apertura de un fichero:
Para procesar un Archivo en C ( y en todos los lenguajes de programacin) la primera operacin que hay que realizar es abrir el archivo. La apertura del archivo supone conectar el archivo externo con el programa, e indicar como va a ser tratado el archivo: binario, o de texto, etc. El programa accede a los archivos a travs de un puntero a estructura FILE, la funcin de apertura devuelve dicho puntero. Esta funcin se denomina fopen() y su formato es fopen(nombre_archivo, modo); Donde nombre_archivo es una cadena y modo tambin es otra cadena de carcter. La funcin devuelve un puntero a FILE a travs de dicho puntero el programa hace referencia al archivo. Ejemplo: FILE *pf; pf=fopen(Mi_archivo.dat, r); la funcin puede detectar error al abrir el archive, por ejemplo que este no exista, entonces la funcin retornara NULL. Ejemplo: Se desea abrir un fichero de nombre cuadernos.dat que se encuentra en la raz del disco duro. #include<stdio.h> #include<stdlib.h> FILE * pf; char Nom*+=C:\cuadernos.dat; pf=fopen(Nom, r); if(pf==NULL) { puts(error al abrir fichero para escribir); exit(1); }
Pgina 3
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len w a r+ w+ a+ Abre para escritura( si ya existe se pierden los datos) Abre para aadir al final Abre archivo ya existente para modificar (leer /escribir) Crea un archivo para escribir/leer( si ya existe se pierden los datos) Abre el archivo para modificarlo (escribir /leer) al final. Si no existe es como w+
En estos modos no se ha establecido el tipo de archivo, de texto o binario. Siempre hay una opcin por defecto y aunque depende del compilador utilizado suele ser de modo texto. Para no depender del entorno es mejor indicar si es texto o binario. Se utilizara t para texto y b para binario. Es decir: rt, wt,at,r+t,w+t,a+t o bien rb, wb,ab,r+b,w+b,a+b. Ejemplo. Se quiere abrir fichero de texto con nombre libros.txt y guardarlo como binario en recuerdo.dat (poner operaciones de apertura) #include<stdio.h> #include<stdlib.h> main() { FILE *pf1, *pf2; char primer*+=C:\\libros.txt; char segundo*+=C:\\recuerdo.dat; pf1=fopen(primer, rt); pf2=fopen(segundo, wb); if(pf1==NULL ||pf2==NULL) { puts(Error al Abrir Fichero ); Exit(1); } }
Pgina 4
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len Estas funciones tienen mucho parecido a las funciones asociadas a los flujos( stdin y stdout) teclado scanf () y pantalla fprint() o bien a getchar(), putchar(), gets() y puts() cada una tiene su versin para archivo que inician con la letra f. Asi: fprintf(), fscanf(),fgets() , fputs(), fgets().
4.1 Veamos ahora la funcin para guardar datos carcter a carcter funciones putc() y fputc()
Estas funciones son idnticas putc() est definida como macro, escribe un carcter asociado con el puntero a FILE. Devuelven el carcter escrito o un EOF si no se realizo la escritura para ambas el formato es: fputc( c, puntero_File); putc(c, puntero_File); Donde c es el carcter escrito. Ejemplo: Se creara un fichero de nombre salida.dat con los caracteres que se tecleen. #include<stdio.h> #include<stdlib.h> int main() { char c; FILE *pf; char *salida=Salida.dat; if((pf== fopen(Salida,wt) ==NULL) { puts(ERROR EN OPERACION DE APERTURA ); return 1; } while((c=getchar()) !=EOF) { putc(c,pf); //aqu se puede utilizar fputc(c, pf); } return 0; } Ahora veremos funciones para leer de un fichero carcter a carcter sean estas las funciones getc() y fgetc() estas funciones son iguales igual formato igual funcionalidad; pueden considerarse que son reciprocas de putc() y fputc() . Estas funciones leen un carcter del archivo asociado con el puntero a FILE. Devuelve un el carcter ledo o bien un EOF si no pudo leer. Formato c=getc(puntero_File); c=fgetc(puntero_File); Ejemplo en el ejemplo anterior se cre un archivo de nombre Salida.dat que est guardado en el disco realizaremos el programa que lea su contenido y lo muestre por pantalla y que cuente el nmero de lneas. A continuacin se presenta el programa para leer ese fichero haciendo uso de las funciones de lectura en ficheros carcter a carcter.
Pgina 5
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len #include<stdio.h> #include<stdlib.h> int main() { char c; int n=0; FILE *pf; char *nombre=Salida.dat; if((pf== fopen(nombre,rt) ==NULL) { puts(ERROR EN OPERACION DE APERTURA ); return 1; } while((c=getc(pf)) !=EOF) // aqu se puede sustituir por fgetc(pf) { if(c==`\n`) { n++; printf(\n); } else putchar(c)
4.2 Funciones que escriben y Lee en fichero cadena a cadena funciones fputs() y fgets().
Estas funciones escriben /leen una cadena en el archivo asociado con el puntero FILE. La funciones fputs() y puts() escriben una cadena de carcter esta funcin devuelve un EOF si no pudo escribir la cadena y un valor positivo si escribi correctamente el formato es : fputs(cadena, puntero_File); La funcin fgets() lee una cadena de carcter del archivo. Termina la captacin de la cadena hasta encontrar el carcter de fin de lnea, o bien cuando ha ledo n-1 caracteres, siendo n el argumento entero de la funcin. Esta funcin devuelve un puntero a la cadena devuelta, o un NULL si ha habido un error. El formato es fgets(cadena, n, puntero_File); El siguiente programa da lectura al archivo cartas.dat que tiene un texto al que se desea aadir nuevas lneas de longitud mnima de 30 carcter, desde el archivo primero.dat
#include<stdio.h> #include<stdlib.h> #include<string.h> #define MX 121 #define MN 30 void main() { FILE *in, *out; char nomb1[]="Carta.dat"; char nomb2[]="Primero.dat"; char cad[MX]; in=fopen(nomb2, "rt"); out =fopen(nomb1 ,"at"); if(in==NULL ||out ==NULL) { puts("Error al abrir archivos "); exit(1);
Pgina 6
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len
Pgina 7
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len
Pgina 8
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len
5. Archivos binarios.
Para abrir un archivo modo binario hay que especificar la opcin b en el modo de apertura. Los archivos binarios son secuencias de ceros y unos. Una de las caractersticas de los archivos binarios es que optimizan la memoria ocupada por un archivo, sobre todo con campos numricos. As , almacenar un entero en modo binario supone una ocupacin de (2 bytes o de 4 bytes segn el sistema un float son 4 bytes o bien 8 bytes , en modo texto el valor numrico se convierte primero a una cadena de carcter (%d o %f) y despus se escribe en el archivo. Ejemplo FILE *pfb; pfb=fopen(Comunicacin, rb); Fundamentalmente para trabajar con valores binarios el lenguaje C nos proporciona dos funciones especiales dirigidas a entradas y salidas a archivos binarios con buffer, son fread() y fwrite().
Pgina 9
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len esta funcin devuelve el nmero de elementos escritos si este es menor que num_elementos es que ha ocurrido un error Ejemplo: En este ejemplo se abre el archivo en forma binario para escritura. Se escriben nmeros reales en doble precisin en el bucle for. El buffer es la variable x, el tamao lo devuelve el operador sizeof. // Trozo de programa FILE *fd; double x; fd=fopen(reales,wb); for(x=0.5; x>0.01; ) { fwrite(&x, sizeof(double),1 fd); X=pow(x, 2); } Los archives binarios estn indicados especialmente para guardar registros, estructuras en C el mtodo habitual es la escritura sucesiva de estructuras en el archivo asociado al puntero, la lectura de estos archivo es similar.
Pgina 10
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len
/********Abrir el Fichero datos para escribir ********/ if((pf=fopen("datos","w"))== NULL) { puts(" El Fichero no se pudo abrir "); exit(1); } /******** Entrada de los datos *******/ printf(" Introduzca la marca de fin de fichero (EOF)para terminar Ctr +z \n\n"); printf(" Referencia : "); while(gets(reg.referencia)!=NULL) { printf("Precio: "); gets(sprecio); reg.precio=atol(sprecio); if(ferror(pf)) /****** Aqu escribe el registro al fichero abierto ***/ fwrite(®, bytesreg, 1, pf); { } } perror("Error durante la escritura "); exit(2); ");
printf(" Referencia :
fclose(pf); // cerrar fichero clearerr(stdin); // desactiva el indicador eof de stdin do { printf(" Quiere visualizar el fichero guardado S/N \n"); respuesta=getchar(); fflush(stdin); }while(tolower(respuesta)!='s' && tolower(respuesta)!='n'); /*********Salida de Datos ******/ if(respuesta =='s') { /*******Aqu se abre el fichero datos para leer *****/ if((pf=fopen("datos","r"))==NULL) { printf(" El Fichero no pudo abrirse \n"); exit(3); } /*******Leer el primer registro del Fichero********/ fread(®,bytesreg,1, pf); while(!ferror(pf) && !feof(pf)) { printf("Referencia : %s\n",reg.referencia); printf("Precio : %ld\n\n", reg.precio); /********* Ahora pasa a leer el otro registro ******/ fread(®, bytesreg,1,pf); }
Pgina 11
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len
6.1 setbuf
Esta funcin permite al usuario controlar la memoria intermedia asignada al fichero apuntado por pf. Esta funcin se deber ejecutar despus de abierto el ficher. Sintaxis Void setbuf(FILE * pf, char *buffer);
6.2 setvbuf
Esta funcin permite decidir al usuario no trabajar con un buffer y el tamao del mismo. Tambin esta funcin se tiene que ejecutar despus de abierto el fichero. Sintaxis int setvbuf(FILE * pf, char *buffer, int tipo, size_t n); buffer es un array de carcter de longitud n bytes desempea la funcin de buffer o memoria intermedia. Tipo _IOFBF _IOLBF _IONBF Significado Se utiliza buffer de tamao n bytes Esto para MSDOS igual que anterior _OFBF No utiliza Buffer
7. Acceso aleatorio
Los programas que se han trabajado tiene acceso secuencial es decir desde el comienzo al final, el acceso aleatorio permite acceder a un registro sin tener que pasar por los antecesores. Las funciones que nos ayudan en esto son las siguientes.
7.1 fseek
La funcin fseek mueve el puntero de lectura y escritura asociado al fichero apuntado por pf, a una nueva localizacin desplazada desp bytes de la posicin pos dada en el argumento, este desp puede ser positivo o negativo. Sintaxis Int fseek(FILE *pf, long desp, int pos);
Pgina 12
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len Los argumentos pos pueden ser los siguientes. pos Definicin SEEK_SET Principio dl fichero SEEK_CUR Posicin Actual del puntero lectura escritura SEEK_END Final del Fichero Esta funcin devuelve 0 si ocurre un error y un valor distinto de cero en caso contrario.
7.2 ftell
Esta funcin da como resultado la posicin actual del puntero de lectura y escritura, del fichero apuntado por pf esta posicin es relativa al principio del fichero. Sintaxis long ftell(FILE *pf); Esta funcin devuelve la posicin actual del puntero L/E o un -1L (es -1 long) si ocurre un error. Ejemplo Long pos; pos =ftell(pf); Ejemplo: #include<stdio.h> #include<stdlib.h> typedef struct { char referencia[20]; long precio; }registro; void main() { registro reg; int bytesreg=sizeof(reg); FILE *pf; int totalreg; int nreg; long desp; int c, respuesta; char sprecio[10]; /********Abrir fichero datos para leer y escribir ******/ if((pf=fopen("datos","r+"))==NULL) { printf("Error no se pudo abrir fichero "); exit(1); } /***Calcular el nmero de registros existentes ******/ fseek(pf, 0L, SEEK_END); totalreg=(int)ftell(pf)/bytesreg; /************Presentar un registro en pantalla******/ do { printf("No de Registro entre 1 y %d (0 para salir) ; ",totalreg); c=scanf("%d",&nreg); fflush(stdin); /******** Visualiza un registro ******/ if(c && (nreg>=1) && (nreg<= totalreg))
Pgina 13
Ficheros en C Departamento de computacin Fac. Ciencias y Tecnologa UNAN-Len { desp=(long)(nreg-1)*bytesreg; fseek(pf,desp,SEEK_SET); fread(®,bytesreg, 1,pf); if(ferror(pf)) { printf(" Error al leer un registro del fichero \n"); exit(2); } printf("\nReferencia: %s\n",reg.referencia); printf("Precio: %ld\n\n",reg.precio); /**************Modificar registro seleccionado ****/ do { printf(" Desea modificar este registro? S/N\n"); respuesta=getchar(); fflush(stdin); }while(tolower(respuesta !='s') && tolower(respuesta)!='n'); if(respuesta == 's') { printf("\nReferencia : "); gets(reg.referencia); printf("Precio : "); gets(sprecio);reg.precio=atol(sprecio); /************Escribir el registro en el Fichero *****/ fseek(pf,-bytesreg, SEEK_CUR); fwrite(®, bytesreg, 1,pf); if(ferror(pf)) { printf("Error al Escribir el registro en Fichero \n"); exit(3); } } } } }while(nreg); fclose(pf);
Bibliografa:
Curso de programacin C /C++ Fco. Javier Ceballos Sierra (Editorial RAMA) Programacin en C Luis Joyanes Aguilar /Ignacio Zahonero Martinez (Editorial MC Graw Hill) Plan Docente Programacin I y II Ral Hermgenes Ruiz C.