Você está na página 1de 16

Capitulo 6

Capitulo 6
1.

Accesos a archivos.

1. Archivos.
Hasta el momento, cuando realizamos un programa, la entrada o salida (E/S), solo la hemos manejamos en el teclado y con el monitor. Sin
embargo, en la prctica pueden ocurrir los siguientes casos:
La cantidad de datos que requiere el programa, es tal, que no es practico introducirlos cada vez que se desee ejecutar. Adems,
estaramos muy propensos a cometer errores al teclearlos.
La cantidad de resultados que genera el programa, es tal, que no es practico intentar leerlos cada vez que se ejecuta. Adems,
estaramos muy propensos a que se nos pasara leer alguno de los resultados.
Algunos programas requieren que otros programas le manden sus resultados para poder trabajar. No seria practico, que nosotros,
leyramos la salida de un programa y se la tecleramos a otro.
Es frecuente que la informacin de alguna compaa se almacene en la computadora. Los programas que la van a manejar deben de
leerla directamente de ah.
El teclado y el monitor, no son los nicos dispositivos de E/S.
Por estas y otras razones, los programas deben leer y escribir informacin en lo que se conoce como archivos. Un archivo es un conjunto de
datos almacenado en memoria secundaria, que se referencia por un nombre. Este nombre depende del sistema operativo.
Las funciones de E/S con la que vamos a trabajar en esta parte han sido diseadas para manejar archivos almacenados en disco bajo un nombre
propio.

1. Flujos
El manejo de archivos en C es mas eficiente que en otros lenguajes, ya que es independiente de la naturaleza fsica del archivo. Este puede
estar en disco, cinta, ser la impresora, etc. En otros lenguajes se debe de considerar el tipo de dispositivo.
El C trata la E/S de archivos en trminos de flujo de datos, algo parecido a canales a travs de los cuales fluyen datos. Podemos desplazarnos
por el flujo, corriente arriba o corriente abajo, buscando un bit en particular, o buscando el ltimo bit o el penltimo.
Existen varias funciones de acceso a archivos. Nosotros vamos a tratar con las siguientes, que son las ms comunes:
fopen(), fclose(), perror(), exit().
getc(), putc().
fgets(), fputs().
fprintf(), fscanf().
getw(), putw().
feof(), ferror().
fread(), fwrite().
fseek(), rewind(), ftell().
remove(), rename().
fflush(), ffushall().

1. fopen(), fclose(), perror(), exit()


Empezaremos por las ms indispensables que son fopen() y fclose(). Esta pareja de funciones se usa para abrir y cerrar los flujos-archivo en
un determinado programa. Esto es anlogo al manejo de archivos en una oficina. Para manejar un archivo, primero hay que abrir el folder que
lo contiene. Al terminar debemos de cerrarlo.
La funcin fopen() abre los archivos para leer, escribir o aadir. El aadir implica escribir en el archivo preservando su contenido, es decir; se
escribe al final del archivo. Los archivos siempre deben haber sido abiertos con fopen() antes de intentar accesarlos con cualquiera de las
restantes funciones de entrada salida que tratamos en esta capitulo.
Las funciones de E/S para archivos estn definidas en el header stdio.h. El prototipo de fopen es:

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

FILE * fopen(char * nombre_archivo, * modo);

fopen() proporciona un apuntador a FILE. FILE es el nombre de una estructura definida en stdio.h. Esta estructura es empleada por las rutinas
de E/S para almacenar informacin sobre el flujo-archivo una vez que ha sido abierto para lectura o escritura. El valor proporcionado por
fopen() es un apuntador que identifica de forma unvoca al archivo. Una vez abierto, nunca nos volvemos a referir a l por su nombre. En
lugar de eso, lo identificaremos por el apuntador que fopen() nos haya proporcionado.
Por default, automticamente, al trabajar en un programa en C, tenemos abiertos 3 flujos:
stdin: Entrada estndar, es decir, el teclado.
stdout: Salida estndar, es decir, el monitor.
stderr: Error estndar, es decir, el monitor.
El flujo stderr se emplea para manejar los mensajes de error que se generan al ejecutar un programa. Por ejemplo al tratar de dividir entre 0.
Cuando esto ocurre, se genera un mensaje de error por parte del sistema operativo. Normalmente estos mensajes se envan al monitor.
Algunos compiladores ofrecen otros flujos por default. Turbo C ofrece:
stdaux: Dispositivos auxiliares.
stdprn: Impresora.
Estos flujos no forman parte del estndar ANSI, ya que los dispositivos como la impresora son muy variados.
La sintaxis de la funcin nos indica que fopen() toma argumentos: nombre_archivo y modo. Ambos son apuntadores a
carcter,nombre_archivo es el nombre del archivo que se desea abrir. Este nombre puede contener si se requiere el path, donde este el archivo.
Es importante notar que en este caso debes emplear \\ en vez de \ para dar el path.
Existen 2 formatos para manejar los archivos:
modo texto.
modo binario.
Un archivo de texto, consta de caracteres ASCII. Esta dividido en lneas. Cada lnea esta constituida por una secuencia de caracteres ASCII y
al final tiene el carcter salto de lnea. Al final del archivo, se halla un carcter especial, el cual indica el fin del archivo. Este carcter se
representa por la macro EOF, su valor depende del sistema operativo. Usualmente es un valor entero negativo. Para teclear este carcter se usa
por lo regular la tecla CTRL seguida de otra. Por ejemplo en DOS se puede dar este carcter con ctrl-Z y en UNIX con ctrl-D.
En un archivo binario los datos se manejan directamente como se almacenan en memoria, es decir como una secuencia de bits. Estos archivos
se hallan organizados como una secuencia lineal de bytes. Al final tambin tienen el carcter EOF. No se insertan caracteres '\n'.
Cada formato tiene ventajas y desventajas:
En modo texto los archivos son legibles para el usuario.
Se pueden crear y manejar con cualquier editor de texto.
Ocupan mucha memoria ya que cada dato se escribe como una secuencia de caracteres ASCII, adems de los caracteres '\n' en cada
lnea.
Al guardar datos de tipo float o double, estos tienen que redondearse, con la consabida perdida de precisin.
En modo binario los archivos no son legibles para el usuario, ya que se hallan en lenguaje de mquina.
Solo se pueden crear y manejar con un programa.
Ocupan menos memoria ya que cada dato solo ocupa los bytes que se requiere para representarlo. Por ejemplo se escribimos 32767 en
modo binario solo ocupa 2 bytes. En modo texto se escribe como una secuencia de caracteres ASCII, por lo que ocupa 5 bytes, adems
de los caracteres '\n' en cada lnea.
Al guardar datos de tipo float o double, estos no se tienen que redondear, ya que se almacenan tal y como se representan en la memoria.
Por esta razn no hay perdida de precisin.

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

El modo puede ser una de las siguientes cadenas:


"r": Abre un archivo para lectura, en modo texto. Si el archivo no existe se genera un error.
"w": Abre un archivo y escribe datos en l, en modo texto . Si el archivo no existe, lo crea. Si ya existe ese archivo, su contenido actual
se pierde.
"a": Abre un archivo para aadirle datos, en modo texto. Si el archivo no existe, se crea. Si ya existe ese archivo, su contenido actual se
preserva.
"rb": Abre un archivo para lectura, en modo binario. Si el archivo no existe se genera un error.
"wb": Abre un archivo y escribe datos en l, en modo binario . Si el archivo no existe, lo crea. Si ya existe ese archivo, su contenido
actual se pierde.
"ab": Crea y abre un archivo para aadirle datos, en modo binario, si el archivo no existe. Si ya existe ese archivo, su contenido actual
se preserva.
"r+","w+": Abre un archivo para lectura-escritura, en modo texto.
"r+b", "w+b": Abre un archivo para lectura-escritura, en modo binario.
Como podemos observar los modos se especifican como cadenas y no como caracteres; esto se nota en el hecho de que se escriben entre
comillas.
El ejemplo siguiente muestra como se usa fopen() en un programa. En este fragmento de cdigo , lo primero que hacemos es declarar dos
apuntadores a flujo, archivo_ent y archivo_sal, que proporciona valores de tipo FILE *.
#include <stdio.h>
FILE * archivo_ent, * archivo_sal;
archivo_ent=fopen("entrada","r"); /* entrada esta abierto para lectura */
archivo_sal =fopen("salida","w"); /* salida esta abierto para escritura */
Una vez declarados los apuntadores, abrimos el archivo entrada para lectura y guardamos su apuntador bajo el nombre archivo_ent. De forma
anloga, abrimos el archivo salida para escritura y guardamos su apuntador bajo el nombre archivo_sal. Ms adelante en el programa usaremos
siempre los nombres de los apuntadores para referirnos a estos dos archivos
Puede ocurrir que no consigamos abrir dicho archivo. A lo mejor estamos pidiendo que se lea un archivo que no existe o para el que no
tenemos permiso de lectura; quizs estamos intentando crear un archivo que ya existe y no tengamos permiso para borrarlo; puede ser que
hayamos excedido el nmero mximo de archivos que pueden estar abiertos a la vez en nuestro sistema, o pudiese ser que ya no hubiese
espacio en disco. Siempre que, por cualquier razn, fopen() no puede abrir un archivo, regresa un apuntador NULL, que en stdio.h esta
definido as:

#define NULL ((void *)0)

Ya que el sistema operativo puede negarse a abrir un archivo, el programador prudente siempre comprueba los valores proporcionados por
fopen().
Esto se realiza mediante las siguientes lneas que deben incluirse en cada programa:
if((archivo_ent=fopen("secretos","r"))= =NULL)
{
perror("no puedo abrir el archivo secretos\n");
exit(EXIT_FAILURE);
}

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

else if ((archivo_sal = fopen("chismes","w")) == NULL)


{
perror("no puedo abrir el archivo chismes\n");
exit(EXIT_FAILURE);
}
Con esto compruebas si en realidad se abre el archivo y estamos en disposicin de poder trabajar con l.
La funcin perror() se usa para mandar el mensaje entre comillas a stderr. Adems de esto tambin se escribe en stderr, el mensaje de error
generado por el sistema operativo. Esto es deseable, para la depuracin. El inconveniente es que el mensaje de error, se halla en el idioma del
sistema operativo. Esta funcin esta en stdio.h. Su prototipo es:

void perror(char * mensaje);

La funcin exit() termina la ejecucin del programa, no importando en que punto de l nos encontremos. La macro EXIT_FAILURE, la
usamos para indicar que el programa termino anormalmente. Si deseas indicar que todo termino bien empleas la macro EXIT_SUCCESS. Esta
funcin requiere el header stdlib.h. Su prototipo es:

void exit(int estado);

En los ejemplos que siguen, para mantener las cosas sencillas, no vamos a incluir la comprobacin de errores, pero debes incluirla siempre.
Cuando ya no vamos a usar un archivo que hemos abierto con fopen(), deberamos cerrarlo con fclose(). La sintaxis de fclose() es:
#include<stdio.h>
:
:
FILE * archivo_ent, * archivo_sal;
:
:
archivo_ent= fopen("secretos","r");
archivo_sal =fopen("chismes","w");
:

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

:
/* cuerpo del programa */
:
:
fclose(archivo_ent);
fclose(archivo_sal);
Al cerrar los archivos con fclose() se ponen en orden los buffers utilizados por el sistema. En realidad, todos los archivos se cierran
automticamente siempre que se termina un programa en C, por lo que no resulta estrictamente necesario que cerremos explcitamente los
archivos. Tendremos que hacerlo, sin embargo, si vamos a abrir nuevamente el mismo archivo en un modo diferente, o si se da el caso de que
excedamos el nmero de archivos que pueden estar abiertos en nuestro sistema a la vez.
Si fclose() logra cerrar un archivo, el valor regresado es un cero. Si no lo logra, proporcionar EOF, que es un valor dependiente del sistema
que sirve para marcar el fin de archivo y est definido en stdio.h. Tambin es prudente verificar el valor devuelto por fclose().

1. getc(), putc()
Como getchar y putchar, getc() y putc() son macros definidas en stdio.h. Lo que hace getc() y putc() es transferir un carcter cada vez a un
archivo que haya sido previamente abierto por fopen(). Pueden considerarse como funciones con los siguientes prototipos:
int getc(FILE * apun_flujo);
int putc(int c,FILE * apun_flujo);

Nota que ambas manejan int en vez de char. Esto es por motivos histricos. La principal razn es que el carcter EOF, normalmente se maneja
como un int. Para demostrar el uso de getc() y putc(), el siguiente programa lee lo que introduzcamos por la terminal y lo escribe, carcter a
carcter, en el archivo llamado temp; temp se cierra cuando introducimos el carcter EOF, que dependiendo el tipo de maquina puede ser
control-D o bien control-Z. El programa vuelve a abrir automticamente el archivo temp para lectura, luego lee y enva a nuestra terminal lo
que hayamos escrito en el archivo:
#include<stdio.h>
int main(void)
{
FILE * archivo;
int c;
archivo = fopen("temp","w");
while((c=getchar()) != EOF)
putc(c,archivo);
fclose(archivo);
archivo = fopen("temp","r");
while((c=getc(archivo)) != EOF)
putchar(c);

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

return (0);
}
Este programa funciona de la siguiente manera :
Abrimos el archivo llamado temp solo para escritura, y despus con el ciclo while se obtienen los caracteres de la entrada estndar y
estamos checando que no sea el carcter de fin de archivo, cuando tecleemos dicho carcter se cierra el archivo, para posteriormente
realizar otro ciclo en el cual se debe de abrir el archivo para enviarlo a la salida estndar.
Cuando getc() llega al final de un archivo, o cuando getc() o putc() encuentra alguna clase de error, proporcionara EOF. Es asunto
nuestro el procesamiento de las condiciones de error.

1. fgets(), fputs()
Las funciones fgets() y fputs() leen y escriben cadenas de caracteres. Se emplean con archivos de texto. Este es su prototipo:
char * fgets(char * cadena, int longitud,FILE * apun_flujo);

fgets() lee las cadenas de caracteres de un buffer de memoria, hasta que encuentra un carcter de avance de lnea o hasta que hayan sido ledos
longitud-1 bytes. Cuando se da una de estas condiciones, fgets() aade el carcter nulo '\0' a la cadena. Si la cadena termina con un avance de
lnea, este ser incluido en la cadena y ser agregado el carcter `\0. Este comportamiento implica que siempre que se termine la lnea a leer,
la cadena contendra el carcter salto de lnea. Tienes que tomar en cuenta esto al usar esta funcin.
Si se produce un error, fgets() regresa NULL. Y como siempre es nuestro deber checarlo.
En el caso de fputs(), proporciona una cadena de caracteres hasta, el carcter nulo en el extremo de la cadena, fputs() nunca aade una nueva
lnea.
Si se produce un error, fputs() proporciona EOF.
Ejemplo:
#include<stdio.h>
int main(void)
{
FILE * archivo;
char * cadena[80];
archivo = fopen("temp", "w"); /* abre archivo para salida */
while(gets(cadena) != NULL) /* obtener una cadena de stdin */
fputs(cadena, archivo); /* y enviarla a archivo */
fclose(archivo);
archivo = fopen("temp","r"); /* abre archivo para entrada */
while(fgets(cadena,12,archivo) !=NULL)/* obtener una cadena del archivo */
puts(cadena); /* y enviarla a stdout */
return (0);
}

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

Si nosotros le introducimos el siguiente texto :


ahora es
el tiempo
para todos
los estudiantes
buenos
y las estudiantes
buenas
^z /* Fin de archivo en DOS */
/* la repite pero con la siguiente forma */
ahora esel
tiempopara
todoslos es
tudiantes b
uenos y las
estudiantes
buenas
Ahora si listamos el contenido del archivo tendremos:
ahora esel tiempoparatodoslos estudiantes buenos y lasestudiantesbuenas
Te parece peculiar la salida ? El programa solo esta haciendo lo que le pedimos que haga. Puesto que no hay ningn espacio en blanco al
final de ninguna de las lneas, nuestro texto esta almacenado en temp con las palabras es y el juntas y con las palabras tiempo y para en la
misma forma, como podemos constatar cuando listamos el archivo despus de ejecutar el programa.
Leemos de nuevo el archivo, por medio de fgets con una cadena de doce caracteres de longitud. Pero dado que el archivo esta formado por
una sola lnea larga, en cada llamada a fgets() se leen once caracteres cada vez, lo que produce el resultado que puede verse en el ejemplo. A
propsito, observa que aunque la ltima cadena no acaba con un avance de lnea y no tiene once caracteres de longitud, fgets() la maneja
correctamente.

1. fprintf() y fscanf()
Las funciones fprintf() y fscanf() se comportan como printf() y scanf(), excepto en que, por supuesto, leen y escriben en archivos en vez de
la terminal. fprintf() tiene cierta utilidad como formateador de la salida para informes; fscanf() sirve para imponer una estructura a un archivo
de entrada. Se usan para archivos de texto. Sus prototipos son:
int fprintf(FILE * apun_flujo, cadena_formato, arg1, arg2,..., argn);
int fscanf(FILE * apun_flujo, cadena_formato,argap1,argap2, ,argapn)

El valor proporcionado por fprinf() es el nmero de caracteres enviados al archivo o, si da un error, un nmero negativo. El valor

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

proporcionado por fscanf() es el nmero de elementos que ha podido emparejar. Cuando fscanf() llega al final del archivo, proporciona un
EOF.
Este es un ejemplo del funcionamiento de estas dos funciones:
#include <stdio.h>
int main(void)
{
FILE * archivo;
int i;
archivo = fopen("temp","w"); /* abre archivo para salida */
for (i=0;i<985;i+=123)
fprintf(archivo,"%03d",i); /* formatea i como 3 dgitos y */
/* lo enva al archivo */
fclose(archivo);
archivo = fopen("temp","r"); /* abrir archivo para entrada */
while(fscanf(archivo,"%03d",&i) !=EOF)
printf("%d\n",i); /* lee las cadenas de 3 dgitos, */ /* las convierte a enteros y las */ /* enva como dgitos a stdout */
return (0);
}

1. getw() y putw()
Las funciones que hemos explicado hasta ahora estaban orientadas hacia los caracteres getw() y putw(). Son dos funciones orientadas a
enteros, sus prototipos son:
int getw(FILE * apun_flujo);
int putw(int i,FILE * apun_flujo);

Estas funciones son variantes de nuestras viejas amigas getc() y putc(). En lugar de tomar o poner caracteres sencillos o bytes toman y ponen
tantos bytes como sean necesario para formar una palabra o sea un entero. Este entero por supuesto variara dependiendo de la computadora
donde se ejecuta el programa. Por esta razn estas funciones se emplean solo con archivos binarios.
getw() proporciona el siguiente entero de un archivo. Cuando llega al final del archivo, regresa EOF.
putw() proporciona el valor de su argumento. Si se produce un error, tambin regresa EOF.
En este ejemplo puede verse a estas dos funciones en accin:
#include<stdio.h>
int main(void)
{

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

FILE * archivo;
int i;
archivo = fopen("temp","w"); /* abre el archivo para salida */
for (i=0;i<985;i+=123) /* enva datos enteros al archivo */
putw(i,archivo);
fclose(archivo);
archivo = fopen("temp","r"); /* abre el archivo para entrada */
while((i=getw(archivo)) !=EOF) /* obtiene enteros del archivo */
printf("%d\n",i); /* y enva a stdout como dgitos */
return (0);
}
El punto importante del que hay que estar conscientes es que las funciones putw() y getw() nos permiten manejar enteros como enteros, sin
tener que convertirlos a cadenas de caracteres. Esta es una forma ms eficiente de manejar enteros, pero es menos portable, ya que diferentes
mquinas tendrn diferentes tamaos de palabras y usaran ordenaciones de bytes diferentes para representar los valores enteros. Un archivo
escrito por una mquina puede ser no legible por otra cuando se usan putw() y getw(), a no ser que se emplee una rutina de conversin para
interpretar los resultados. Por esta razn estas funciones no son parte del estndar ANSI.

1. feof(), ferror()
Una pregunta, si al leer de un archivo binario un carcter o un entero es posible que lo que leamos sea un valor tal que coincida con el de
EOF?, podemos distinguir entre el valor de EOF de nuestro sistema y el valor entero que lemos ? Fcil; no podemos. Esto nos conduce
inevitablemente a al discusin sobre las dos funciones de consulta de estado: feof() y ferror().
Estas dos funciones, macrofunciones en realidad, nos permiten consultar el estado de un determinado flujo de E/S para ver si se han dado
condiciones de fin-de-archivo o de error. Sus prototipos son:

int feof(FILE * apun_flujo);


int ferror(FILE * apun_flujo);

Cuando todo va bien, las dos proporcionan un cero. Cuando una funcin de E/S ha ledo al final de un archivo, feof(apun_flujo) proporciona
EOF. Cuando se produce un error en la serie de apun_flujo, ferror(apun_flujo), proporciona un valor no nulo. As que podamos haber escrito
estas lneas a partir de nuestro ltimo ejemplo, de la manera siguiente:
while((i=getw(archivo)) !=EOF)
printf("%d\n",i);
for(;;) /* ciclo sin fin */
{
i= getw(archivo); /* obtener el entero siguiente */

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

if(feof(archivo)) /* comprobar la condicin de EOF */


break; /* hemos llegado al final del archivo */
printf("%d\n",i);
}
De hecho, no estabamos en peligro para nada, puesto que ya sabamos que nunca conseguiramos un nmero negativo a partir de getw() a
menos que hubiramos llegado al final del archivo. Pero tal conocimiento es relativo a nuestro sistema. El uso de feof() hace que el programa
sea portable a otras mquinas.
ferror() es apropiada para checar si ha ocurrido algn error al manejar un archivo. Conviene si se desea saber el error ocurrido usarla en
combinacin con perror().
/* Se supone que ya se abri el archivo para escribir en el */
while (!continuar) {
putc(dato,archi);
if (ferror(archi)) {
perror("\aHorror al manejar el archivo\n");
exit(EXIT_FAILURE);
}
..
.
.
}

1. fread(), fwrite()
Para manejar archivos binarios, se usan 2 funciones. Las funciones fread() y fwrite(). Aunque los datos que manejen estn orientados a bytes,
estas funciones nos permiten agrupar los bytes en paquetes de distintos tamaos, dependiendo de que queramos interpretar luego los bytes
como enteros, como caracteres, como variables estructurada, o como queramos hacerlo. Estas funciones tienen los siguientes prototipos:
int fread(void * buffer, int longitud, int contador,FILE * apun_flujo);
int fwrite(void * buffer, int longitud, int contador,FILE * apun_flujo);

Ambas funciones aceptan los mismos argumentos:


buffer es el lugar de memoria de donde de van a leer los datos o donde se van a escribir. Observa que este argumento esta declarado
como void * buffer. Este argumento debe de poder manejar cualquier tipo de dato, y debe de pasarse como un apuntador ya que se va a
modificar por fread(). Para lograr esto se maneja el apuntador a void. Este apuntador, lo introdujo el estndar ANSI y puede apuntar a
cualquier tipo de dato. Pero hay que pagar un precio: No se puede desreferenciar. Por esta razn debe de convertirse al tipo apropiado
antes de usarlo.
longitud es el tamao en bytes de los elementos de datos a leer y escribir .
contador es el numero de elementos a leer y escribir por la llamada a la funcin. Cada elemento debe ser del tamao especificado por
longitud.
apun_flujo es el apuntador al archivo proporcionado por fopen().

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

Un ejemplo del uso de estas funciones lo da el siguiente cdigo:


#include <stdio.h>
int main(void)
{
FILE * archi, * torombolo;
float x;
archi = fopen("entrada","rb");
torombolo = fopen("salida","wb");
fread(&x,sizeof(x),1,archi);
fwrite(&x,sizeof(x),1,torombolo);
fclose(archivo);
fclose(torombolo);
return (0);
}
En el programa se lee un flotante del archivo entrada y se escribe en el archivo salida. En ambos casos el buffer es la variable x. Usamos sizeof
para calcular el tamao. Manejamos una sola variable. Al final se indica el apuntador al archivo pertinente.
Una de las ventajas que se tienen al manejar archivos binarios, es que ocupan menos memoria que los de texto. Pero hay otras que te
mostraremos a continuacin, modificando el cdigo anterior.
#include<stdio.h>
int main(void)
{
FILE * archi, * torombolo;
float x[1000];
archi = fopen("entrada","rb");
torombolo = fopen("salida","wb");
fread(x,sizeof(x),1,archi);
fwrite(x,sizeof(x[0]),1000,torombolo);
fclose(archivo);
fclose(torombolo);
return (0);
}
Ahora x no es una variable simple, sino un arreglo. En el fread, empleamos sizeof para calcular el tamao del arreglo e indicamos que leemos
un solo objeto de ese tamao. En el fwrite obtenemos el tamao de un elemento del arreglo y escribimos mil objetos de ese tamao. La ventaja
de usar un archivo binario aqu, sobre un archivo de texto es que la lectura o escritura la hicimos en un solo paso. En modo texto se tendra que
usar un ciclo, con el consabido gasto de mayor tiempo.

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

#include<stdio.h>
typedef struct Hoja {
char nombre[20], domicilio[40], telefono[20];
int edad;
char sexo;
} hoja;
int main(void)
{
FILE * archi, * torombolo;
hoja x;
archi = fopen("entrada","rb");
torombolo = fopen("salida","wb");
fread(&x,sizeof(x),1,archi);
fwrite(&x,sizeof(x),1,torombolo);
fclose(archivo);
fclose(torombolo);
return (0);
}
Es este caso x es una estructura. Se esta manejando en un solo paso la lectura y la escritura. Si deseramos hacer esto en modo texto, se tendra
que manjar por separado una instruccin con cada campo de la estructura.
#include<stdio.h>
typedef struct Hoja {
char nombre[20], domicilio[40], telefono[20];
int edad;
char sexo;
} hoja;
int main(void)
{
FILE * archi, * torombolo;
hoja x[500];
archi = fopen("entrada","rb");
torombolo = fopen("salida","wb");
fread(x,sizeof(x[0]),500,archi);

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

fwrite(x,sizeof(x),1,torombolo);
fclose(archivo);
fclose(torombolo);
return (0);
}
En este caso si se quisiera usar modo texto se tendra que manejar por separado los campos y adems usar ciclos.
Una ventaja adicional de los archivos binarios, es el manejar tipos de datos complejos en un solo paso. Otra ventaja es el acceso aleatorio o
directo. Esto es, se puede leer o escribir en cualquier parte del archivo. Esto lo veremos con la siguientes funciones.

1. fseek(), rewind(), ftell()


Hasta ahora hemos tratado las funciones de E/S que leen y escriben archivos de principio a fin, es decir, secuencialmente, pero hay una forma
de eludir esta limitacin. La funcin fseek() nos permite leer o escribir en cualquier punto de un archivo abierto por fopen(). Solo se
recomienda su uso con archivos binarios, ya que en archivos de texto, la presencia de los '\n' puede producir errores al realizar los
desplazamientos. El prototipo de fseek() es:
int fseek(FILE * apun_flujo, long int offset,int modo);

El argumento de desplazamiento offset nos permite posicionarnos para la siguiente lectura o escritura, segn sean los valores de offset y de
modo:
Si el valor de modo es la macro SEEK_SET o 0, offset es el nmero de bytes desde el principio del archivo.
Si el valor de modo es la macro SEEK_END o 2, offset es el nmero de bytes desde el final del archivo.
Si el valor de modo es 1 o la macro SEEK_CURR o 1, offset es el nmero de bytes con respecto del byte actual dentro del archivo.
Puesto que el valor de offset puede ser negativo, podemos movernos hacia adelante y hacia atrs a voluntad. fseek() proporciona un cero a no
ser que intentemos poner o tomar un valor fuera de los limites del archivo.
Como ejemplo, el siguiente programa abre el archivo test.c y lo imprime hacia atrs en nuestra terminal. Observa que el valor de offset es un
long:
#include<stdio.h>
int main(void)
{
FILE * archivo;
archivo = fopen("test.c","rb"); /* abre el archivo para entrada */
fseek(archivo,0L,2); /* busca el final del archivo */
do
{
putchar(getc(archivo)); /* imprime el siguiente ciclo */
}
while(!fseek(archivo,-2L,1));

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

return (0);
}
Por qu crees que hay un -2L en el segundo fseek() ? Cada vez que leemos un byte avanzamos una posicin en el archivo, lo que significa
que tenemos que retroceder dos veces para poder tomar el byte anterior. Por qu ponemos -2L ? Por que fseek() espera que en esa posicin
haya un valor long, y no vamos a arriesgar a que no sea as.
La funcin rewind() se puede usar tanto con archivos binarios como de texto. Esta funcin solo nos ubica al principio del archivo. Si tiene
xito nos regresa 0.
La funcin ftell() es un complemento a fseek(). Esta funcin te dice donde estas, es decir, te regresa la posicion actual en el archivo, tomando
como punto de referencia el principio del archivo. regresa -1L en caso de error. Su prototipo es:

long ftell(FILE * archivo);

Como ejemplo el siguiente programa copia un archivo al revs:


#include <stdio.h>
int main(int argc,char * argv[])
{
char entrada[81],salida[81];
long pos;
FILE * archi, * torombolo;
if (argc != 3) {
perror("Numero de argumentos invalido \n");
exit(EXIT_FAILURE);
}
archi = fopen(entrada, "rb"); /* abre el archivo para entrada */
torombolo = fopen(salida, "rb"); /* abre el archivo para salida */
fseek(archi, 1L, SEEK_END); /* busca el final del archivo */
pos = ftell(archi); /* Nos indica donde estamos */
while(pos)
{
putc(getc(archi),torombolo); /* copia un byte */
fseek(archi, -2l, SEEK_END);
pos = ftell(archi);

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

}
putc(getc(archi),torombolo); /* copia el ultimo byte */
fclose(archi);
fclose(torombolo);
exit(EXIT_SUCCESS);
}
Por supuesto falta validar los resultados de fopen y de fclose. Con fseek nos posicionamos al final del archivo de entrada. ftell nos da la
posicion actual. Copiamos carcter a carcter el archivo de entrada en el de salida. Con fseek retrocedemos 2 bytes hacia atrs, ya que al leer
avanzamos 1. Cuando ftell nos de 0, implica que estaremos al principio del archivo, con lo cual habremos terminado de copiar. La macro
EXIT_SUCCESS nos indica que terminamos bien.

1. remove(), rename()
La funcin remove() borra un archivo. Su prototipo es:
int remove(char * archivo);

En caso de error regresa un valor distinto a 0. Si es necesario el nombre del archivo puede incluir un path.
La funcin rename() cambia el nombre de un archivo, en caso de error regresa un valor distinto a 0. Su prototipo es:

int rename (char * nombre_viejo, char * nombre_nuevo);

1. fflush(), flushall()
Te has topado con problemas al leer usando scanf() o getchar() ? Si es as las funciones fflush() y flushall(), pueden ser tu salvacin.
Cuando leemos datos del teclado, realmente no se van del teclado a las variables que estemos manejando, si no que los datos se van a un buffer.
De este buffer es donde las funciones como scanf() o getchar() toman sus valores.
A veces al trabajar, damos caracteres '\r' de mas o algn otro, y cuando queremos leer algo, las funciones como scanf() toman lo que se halla
en el buffer. Anlogamente tambin pasa esto al manejar archivos, ya que tambin se tienen un buffer por cada archivo abierto.
La finalidad de las funciones fflush() y flushall() es resetear los buffers. Sus prototipos son:

int fflush(FILE * archivo);


int flushall(void);

Si el flujo esta abierto para escritura, el buffer se vaca en el archivo. Si el buffer esta abierto para lectura, solo se vaca el buffer, es decir; su
contenido se pierde. Regresan cero si tienen xito y algn valor distinto en caso de error. fflush() solo resetea un archivo. flushall() resetea
todos los flujos abiertos. Esta ltima funcin, no esta definida en el estndar ANSI. En el siguiente ejemplo se resetea el buffer despus de

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Capitulo 6

leer.
/* Se presupone que ya se abri el archivo */
c=getchar();
fflush();

1. ndice
6. ACCESOS A ARCHIVOS 6-16.1 Archivos. 6-16.2 Flujos 6-26.3 fopen(), fclose(), perror(), exit() 6-26.4 getc(),
putc() 6-86.5 fgets(), fputs() 6-96.6 fprintf() y fscanf() 6-116.7 getw(), putw() 6-126.8 feof(), ferror() 6-136.9
fread(), fwrite() 6-156.10 fseek(), rewind(), ftell() 6-186.11 remove(), rename() 6-216.12 fflush(), flushall() 6216.13 Autoevaluacin 6-236.14 ndice 6-25

http://sai.uam.mx/apoyodidactico/pa/Unidad6/pauni6.html[03/03/2010 11:54:19 a.m.]

Você também pode gostar