Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ficheros
Objetivos:
Contenido:
• Conceptos básicos.
• Flujos.
• Operaciones con archivos: abrir, cerrar, leer y escribir.
1
Entrada/Salida con archivos
Todos los programas en C que hemos ejecutado hasta el momento requerían de ingreso de datos
por teclado para realizar determinadas tareas y luego mostrar resultados. Tales programas tienen
un gran defecto y es que los datos que se cargan desaparecen cuando el programa termina, por lo
tanto cada vez que se ejecuta el programa hay que cargar los datos nuevamente.
Para solucionar este problema debería de existir una forma de almacenar los datos que se ingresan
en un archivo que se almacena en el disco duro o memoria flash de forma de disponer de la
información en cualquier momento.
Flujo
Un flujo (stream) es una abstracción que se refiere a un flujo o corriente de datos que fluyen entre
un origen o fuente (productor) y un destino o sumidero (consumidor). Entre el origen y el destino
debe existir una conexión o canal por la cual circulen los datos. La apertura de un archivo supone
establecer la conexión del programa con el dispositivo que contiene al archivo.
Estas tres variables se inicializan al comenzar la ejecución del programa y todas ellas admiten
secuencias de caracteres en modo texto. Tienen el siguiente cometido:
stdin asocia la entrada estándar (teclado) con el programa.
stdout asocia la salida estándar (pantalla) con el programa.
stderr asocia la salida de mensajes de error (pantalla) con el programa.
El acceso a los archivos se hace con un buffer intermedio. Se puede pensar en el buffer como un
array donde se van almacenando los datos dirigidos al archivo, o desde el archivo; el buffer se
vuelca cuando de una forma u otra se da la orden de vaciarlo.
2
Por ejemplo, cuando se llama a una función para leer del archivo una cadena, la función lee tantos
caracteres como quepan en el buffer. Luego, la primera cadena del buffer es la que se obtiene; una
siguiente llamada a la función obtendrá la siguiente cadena del buffer, así hasta que se quede vacío
y sea llenado con una posterior llamada a la función de lectura.
Los pasos fundamentales a la hora de operar con ficheros son los siguientes:
Variables de flujo
La librería estándar de C tiene definido un tipo de datos, FILE * que representa un flujo de bytes.
Asociado a este flujo puede estar un archivo, una posición de memoria, el teclado, etc... La
declaración:
FILE *fich;
Declara que la variable fich representará un flujo de datos, que luego asociaremos.
Abrir el fichero
Una vez que tenemos declarada una variable de tipo FILE * tenemos que asociarla con el fichero
que queremos abrir. Esto se hace mediante la llamada fopen.
fopen admite varios modos de apertura de ficheros. Si quisiéramos abrir el fichero para lectura
(esto es, leer los datos que contiene y no modificarlo), utilizaríamos fopen de la siguiente
manera:
Por último es posible que necesitemos añadir datos al final de un fichero ya existente:
fich = fopen( "fichero.txt", "a" );
3
Leer y escribir en un fichero
Lectura
Leer un archivo que tenga un formato determinado es una tarea fácil utilizando la rutina fscanf,
que funciona de forma análoga a scanf.
Supongamos que queremos leer una línea del fichero notas.txt que contiene un listado de notas
de alumnos con el siguiente formato:
#include <stdio.h>
int main(void)
{
int c, n = 0;
FILE *fich;
char nombre[10], apellido1[10], apellido2[10];
float nota1,nota2;
Contenido de notas.txt
4
Una necesidad común a la hora de leer de un archivo consiste en saber cuándo hemos llegado al
final del archivo. Esto se realiza con la rutina feof(), que devuelve un valor distinto de cero cuando
hemos llegado al final del archivo.
Escritura
Cerrar el fichero
Una vez que hemos terminado de operar con el fichero hay que realizar una operación de cierre
sobre la variable asociada, utilizando la rutina fclose(). Una vez que hemos cerrado un fichero
no podremos realizar ninguna operación de lectura/escritura sin antes volver a abrirlo.
fopen
FILE *fopen(const char *nombre_fichero, const char *modo);
fclose
int fclose(FILE *flujo);
5
Cierra el fichero asociado con ``flujo''. Devuelve 0 en caso de éxito y EOF (end of file) en caso
contrario.
fgetc
int fgetc(FILE *flujo);
Lee el siguiente carácter por ``flujo'', avanza el indicador de posición y devuelve int. Devuelve
EOF si pone a 1 el indicador de fin de fichero o el de error.
fgets
char *fgets(char *s, int n, FILE *flujo);
Lee caracteres por ``flujo'' y los almacena en elementos sucesivos del ``array'' que comienza en
``s'', continuando hasta que almacene ``n-1'' caracteres, almacene un carácter del nueva línea o
ponga a 1 los indicadores de error o de fin de fichero.
fputc
int fputc(int c, FILE *flujo);
Escribe el carácter c por ``flujo'', avanza el indicador de posición del fichero y devuelve int c .
En caso de error devuelve EOF.
fputs
int fputs(const char *s, FILE *flujo);
Escribe los caracteres de la cadena s por ``flujo''. No escribe el carácter nulo de terminación. En
caso de éxito, devuelve un valor no negativo; en caso de error devuelve EOF.
fscanf
int fscanf(FILE *flujo, const char *formato, ...);
6
fprintf
int fprintf(FILE *flujo, const char *formato, ...);
Genera texto formateado, bajo el control de formato formato y escribe los caracteres generados
por flujo. Devuelve el número de caracteres generados o un valor negativo en caso de error.
A modo de resumen estas son las especificaciones de formato más comunes:
Formato Descripción
%d Entero con signo
%u Entero sin signo
%c Caracter
%s Puntero a cadena de caracteres
función feof(archivo)
Permite saber si el puntero está al final o no del archivo, esta devuelve el resultado 0 si
se encuentra en el final de archivo o #0 si se encuentra en cualquier otra parte del mismo.
fwrite
size_t fwrite(const void *buffer, size_t n, size_t c, FILE *flujo);
fread
size_t fread(const void *buffer, size_t n, size_t c, FILE *flujo);
La rutina fread permite leer c elementos de longitud n bytes del fichero apuntado por ``flujo'' y
los almacena en el buffer especificado.
7
Acceso aleatorio:
❖ ftell( ) : Permite obtener la posición en el fichero del puntero de L/E
❖ rewind( ): Coloca el localizador de posición del archivo al principio del mismo.
❖ fseek:
origen :
comienzo del archivo SEEK_SET 0
posicion actual SEEK_CUR 1
fin de archivo SEEK_END 2
#include <stdio.h>
#define SIZE 20
main()
{
FILE *fp;
char ch;
Detección de errores:
8
Ejemplo:
if(ferror(pf))
{
printf(“Error: No se puede realizar la operación sobre el archivo”);
clearerr(pf);
}
EJERCICIOS:
fputc()
Se desea crear un archivo SALIDA.TXT con los caracteres introducidos por teclado.
Una vez abierto el archivo, un bucle while no sea fin de archivo(macro EOF) lee
carácter a carácter y se escribe en el archivo asociado al puntero FILE.
//fputc1.c
#include <stdio.h>
int main()
{
int c;
FILE *pf;
char salida[] = "SALIDA.TXT";
9
if((pf=fopen(salida,"w")) == NULL)
{
puts("ERROR EN LA OPERACION DE APERTURA");
return 1;
}
fclose(pf);
return 0;
}
fgetc() :
//fgetc1.c
#include <stdio.h>
int main(void)
{
int c, n = 0;
FILE *pf;
char nombre[]="SALIDA.TXT";
if((pf=fopen(nombre,"r")) == NULL)
{
puts("ERROR EN LA OPERACION DE APERTURA");
return 1;
}
10
while((c=fgetc(pf))!=EOF)
{
if(c == '\n')
{
n++;
printf("\n");
}
else
putchar(c);
}
//fputc2.c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void main(void)
{
FILE *fpt;
char c;
fpt=fopen("muestra.dat","w");
do
fputc(toupper(c=getchar() ),fpt);
while(c!='\n');
fclose(fpt);
}
11
El siguiente programa lee una línea de texto del archivo muestra.dat, carácter a
carácter y muestra el texto en la pantalla.
//fgetc2.c
#include <stdio.h>
void main(void)
{
FILE *fpt;
char c;
if((fpt=fopen("muestra.dat","r")) == NULL)
printf("\nError - No se puede abrir el archivo indicado\n");
else
do
putchar(c=fgetc(fpt));
while(c!='\n');
fclose(fpt);
}
Este programa copia el contenido de un fichero de texto en otro fichero con nombre distinto. El
programa pedirá en primer lugar el nombre de un fichero ya existente; una vez introducido dicho
nombre pedirá otro nombre que será el del nuevo fichero donde irá la copia. Con estos datos, el
programa realizará una copia del texto contenido en el primer fichero en otro fichero con el segundo
nombre en el mismo directorio.
Nota: La resolución del problema es muy sencilla: basta con abrir dos ficheros: uno de lectura y
otro de escritura, que contengan respectivamente el fichero original y el fichero copia. Una vez
abiertos estos ficheros, se leen las cadenas del fichero original y se copian en el fichero copia., Para
ello se emplea el bucle while.
/* fichero copiar.c */
#include <stdio.h>
#include <stdlib.h>
//fgets1.c
void main()
{
char ch[80];
char file1[13], file2[13];
12
FILE *f1, *f2;
//fgets2.c
#include <stdio.h>
#include <stdlib.h>
void main()
{
char ch[80];
char file1[13], file2[13];
FILE *f1, *f2;
f2 = fopen(file2, "a");
if(!f1)
printf("Fichero %s no existe!!", file1);
else
while ((fgets(ch,80,f1)) != NULL)
fputs(ch,f2);
fclose(f1);
fclose(f2);
}
13
Ejemplo de fprintf:
//fprintf1.c
#include <stdio.h>
int main(void)
{
int cuenta;
char nombre[30];
float saldo;
FILE *cfptr;
else
{
printf("Introduzca el numero de cuenta, nombre y saldo en una sola linea.\n");
printf("Introduzca EOF para terminar de introducir los datos\n");
scanf("%d %s %f",&cuenta, nombre, &saldo);
while(!feof(stdin))
{
fprintf(cfptr,"%d %s %.2f\n",cuenta, nombre, saldo);
scanf("%d %s %f",&cuenta, nombre, &saldo);
}
fclose(cfptr);
}
return 0;
}
Ejemplo de fscanf:
//fscanf1.c
#include <stdio.h>
int main(void)
{
int cuenta;
char nombre[30];
float saldo;
FILE *cfptr;
14
if((cfptr = fopen("clients.txt","r")) == NULL)
printf("El archivo no pudo ser abierto\n");
else
{
printf("%-10s %-13s %s\n","Cuenta","Nombre","Saldo");
fscanf(cfptr,"%d %s %f",&cuenta, nombre, &saldo);
while(!feof(cfptr))
{
printf("%-10d %-13s %7.2f\n",cuenta, nombre, saldo);
fscanf(cfptr,"%d %s %f",&cuenta, nombre, &saldo);
}
fclose(cfptr);
}
return 0;
}
Este programa crea un archivo para una serie de registros de cliente. La estrategia
general será dar la fecha actual y entrar en un bucle que procesará una serie de registros
de cliente. Para cada cliente se leerá el nombre del cliente, la calle, la ciudad, el número
de cuenta, el saldo inicial(anteriorsaldo), el pago realizado y el saldo actual. A
continuación la fecha actual se asigna a ultimopago. Cada registro de cliente se escribirá
en un archivo de sólo escritura llamado registro.txt. El proceso continuará hasta que el
nombre de un cliente comience con los caracteres FIN(tanto en mayúscula como en
minúscula). Cuando se encuentre FIN, se escribirá en el archivo de datos indicando una
condición de fin de archivo.
//fprintf2.c
#include <stdio.h>
#include <string.h>
#define CIERTO 1
15
typedef struct
{
char nombre[80];
char calle[80];
char ciudad[80];
int cuen_no; /*entero positivo */
char cuen_tipo; /*C(al día), O(retrasada), M(Moroso) */
float anteriorsaldo; /* cantidad no negativa */
float pago; /*cantidad no negativa*/
float nuevosaldo; /* cantidad no negativa */
struct fecha ultimopago;
}registro;
FILE *fpt;
int main(void)
{
int indicador=CIERTO;
registro cliente;
registro leerpantalla(registro cliente);
void escribirarchivo(registro cliente);
/*bucle principal*/
while(indicador)
{
/* introducir el nombre del cliente y escribirlo en el archivo */
fflush(stdin);
printf("\nNombre(introducir FIN para terminar):");
scanf("%[^\n]",cliente.nombre);
fprintf(fpt,"\n%s\n",cliente.nombre);
/*comprobacion de condicion de parada */
if(strcmpi(cliente.nombre,"FIN") == 0)
break;
cliente=leerpantalla(cliente);
16
escribirarchivo(cliente);
}
fclose(fpt);
return 0;
}
17
Ejercicio con fwrite
typedef struct
{
int numcuenta;
char nombre[40];
char apellido[40];
float saldo;
} registro; // tipo registro
main()
{
char nombreFichero[30]; // nombre del fichero
char resp = 's';
18
int existe(char *nombreFichero)
{
FILE *pf = NULL;
// Verificar si el fichero existe
int exis = 0; // no existe
if ((pf = fopen(nombreFichero, "r")) != NULL)
{
exis = 1; // existe
fclose(pf);
}
return exis;
}
19
// Almacenar un registro en el fichero
fwrite(®, sizeof(reg), 1, pf);
if (ferror(pf))
{
perror("Error durante la escritura");
exit(2);
}
typedef struct
{
int numcuenta;
char nombre[40];
char apellido[40];
float saldo;
} registro; // tipo registro
main()
{
FILE *pf = NULL; // puntero a un flujo
int totalreg = 0; // número total de registros
int nreg = 0; // número de registro
char nombreFichero[30]; // nombre del fichero
int c = 0, respuesta = 0;
20
// Solicitar el nombre del fichero
printf("Nombre del fichero: ");
gets(nombreFichero);
if (respuesta == 's')
modificarReg(pf, nreg);
}
}
while (nreg);
fclose(pf);
}
// Visualizar un registro
desp = (long)(nreg - 1) * bytesPorReg;
fseek(pf, desp, SEEK_SET);
fread(®, bytesPorReg, 1, pf);
if (ferror(pf))
{
printf("Error al leer un registro del fichero.\n");
return;
}
printf("Numero de cuenta: %d\n", reg.numcuenta);
printf("Nombre: %s\n", reg.nombre);
printf("Apellido: %s\n\n", reg.apellido);
printf("Saldo: %f\n",reg.saldo);
}
22
Archivos temporales
#include <stdio.h>
FILE *tmpfile(void);
FILE *pf;
if((pf = tmpfile() ) = = NULL)
printf(“No se puede crear un fichero temporal\n”);
//temporal.c
/*Usando archivos temporales */
#include <stdio.h>
void main(void)
{
FILE *filePtr, *tempFilePtr;
int c;
char fileName[30];
printf("Este programa cambia los tabuladores a espacios en blanco.\n");
printf("Introduzca un nombre de archivo a ser modificado:");
23
scanf("%s",fileName);
if((filePtr=fopen(fileName,"r+"))!=NULL)
if((tempFilePtr=tmpfile() )!=NULL)
{
printf("\nEl archivo antes de la modificacion es:\n");
while((c=fgetc(filePtr)) !=EOF)
{
putchar(c);
fputc(c=='\t' ? ' ':c,tempFilePtr);
}
rewind(tempFilePtr);
rewind(filePtr);
printf("\nEl archivo después de la modificacion es:\n");
while((c=fgetc(tempFilePtr))!=EOF)
{
putchar(c);
fputc(c,filePtr);
}
}
else
printf("No se puede abrir el archivo temporal\n");
else
printf("No se puede abrir %s\n",fileName);
}
Salida:
24
Ejercicios propuestos
1. Hacer un programa que lea n líneas de texto de un fichero, cuente las vocales de cada línea
e imprima el número de la línea y el número de vocales que tiene.
3. Escribir un programa interactivo en C, guiado por menús, que acceda al archivo generado
en el problema anterior y permita ejecutar una de las siguientes operaciones:
❖ Determinar la capital de un país especificado.
❖ Determinar el país cuya capital se especifica.
❖ Terminar la computación.
4. Escriba un programa para concatenar archivos. Los nombres de los archivos han de estar
en la línea de órdenes, el nuevo archivo resultante de la concatenación ha de ser el último
argumento de la línea de órdenes. El número mínimo de argumentos ha de ser 4: nombre del
programa ejecutable, primer archivo, segundo archivo y el archivo nuevo. El programa debe de
comprobar este hecho. Para copiar un archivo se usa la función fgets() que lee una línea del archivo
de entrada, y la función fputs() que escribe la línea en el archivo de salida. En una función
copia_archivo(), se realiza la operación de copia.
Nombre Puntuación
López Juan 45 80 80 95 55 75
Sánchez Carlos 60 50 70 75 55 80
Aráuz Eugenia 40 30 10 45 60 55
Gómez Marcio 0 5 5 0 10 5
Centeno Pedro 90 85 100 95 90 90
Zapata Sandra 95 90 80 95 85 80
a) Escribir un programa que genere un archivo conteniendo las notas de exámenes de los
estudiantes presentados. Cada componente del archivo será una estructura que contenga el
nombre y las notas de los exámenes para un estudiante. Utilice la función fprintf( ) para
escribir datos en el archivo. Ejecutar el programa para usar dicho fichero en el siguiente
inciso.
25
b) Escribir un programa orientado a archivo que procese las notas de exámenes dadas . Leer
los datos del archivo creado en el problema anterior haciendo uso de la función fscanf( ).
Crear un informe que contenga el nombre, las notas de los exámenes y la media de ellas
para cada estudiante. Escribir la salida en un fichero nuevo.
6. Para el sector de ventas de una empresa se necesita realizar un programa con las
siguientes características
En el archivo producto.dat se deben guardar todos los productos que existen para la venta y los
datos que se ingresan para cada producto son los siguientes:
Código de artículo 6 caracteres de longitud y el primer carácter debe ser X
Descripción Puede tener un máximo de 20 caracteres
Precio Precio del producto
Cantidad Cantidad en existencia del producto
En el archivo ventas.dat se deben guardar las ventas realizadas y los datos que se guardan en este
archivo son:
Código de artículo
Cantidad vendida
Fecha de venta
El programa debe contar con un menú de opciones que tenga Carga de productos, Venta de
productos y Salir del programa
Carga de productos: Se ingresan los datos relativos a cada producto y se guarda en el archivo
producto.dat , si el código ya existe en el archivo se debe informar al usuario y no se debe guardar
y si el código no existe se debe agregar al final. Todos los datos ingresados deben ser validados
por funciones.
Venta de productos: Se ingresa el código de producto que se desea vender y la cantidad a vender.
Se busca el código en el archivo producto.dat y si la cantidad existente es suficiente se realiza la
venta escribiendo en el archivo ventas.dat el código , la cantidad vendida y la fecha. Por otra parte
se debe actualizar la cantidad existente en el archivo producto.dat.
Si la cantidad en existencia es insuficiente se debe mostrar un mensaje de error y no se realizará
la venta.
26
Bibliografía:
✓ Deitel H.M., Deitel P. J. Cómo Programar en C/C++ y Java. Cuarta Edición. México.
Prentice Hall. 2004.
27