¡Descarga tema5 y más Apuntes en PDF de Matemáticas solo en Docsity!
TEMA 5: ARCHIVOS
TEMA 5: ARCHIVOS ...........................................................................................................................................................
I NTRODUCCIÓN .....................................................................................................................................................................
TIPOS DE ACCESO .................................................................................................................................................................
TIPOS DE FICHEROS ...............................................................................................................................................................
Ficheros de tipo texto...................................................................................................................................................... Ficheros de tipo binario.................................................................................................................................................. P ROCESAMIENTO DE UN FICHERO ......................................................................................................................................... Abrir fichero ................................................................................................................................................................... Escribir en fichero .......................................................................................................................................................... Leer de fichero ................................................................................................................................................................ Cerrar fichero ................................................................................................................................................................. Otras instrucciones ......................................................................................................................................................... Lectura mediante get(). .............................................................................................................................................. Lectura de estructuras .................................................................................................................................................. Paso de parámetros. ..................................................................................................................................................... EJEMPLOS DE UTILIZACIÓN DE FICHEROS ............................................................................................................................
Introducción
Hasta este momento hemos estado trabajando con información que estaba situada en memoria. Cuando
arrancamos un programa, se genera la información (o se pide al usuario) y se procesa obteniendo unos
resultados.
Cuando el programa termina, la información guardada en memoria se pierde. Si necesitamos volver a
procesar esta información tendremos que proporcionarsela de nuevo al programa.
Una manera de evitar esto es guardando la información de alguna manera 'permanenete' para poder
acceder de nuevo a ella cuando sea necesario.
Un fichero va a ser una estructura donde podremos guardar información de forma permanente, de
manera que la podremos recuperar en cualquier momento.
De esta forma podemos ver que serán necesarias unas operaciones básicas para poder escribir la
información en el fichero y para poder recuperarla y ponerla en memoria.
También serán necesarias unas funciones para abrir el fichero y para cerrarlo.
Tipos de acceso
Al estar en memoria secundaria, no todos los elementos del fichero son accesibles de forma inmediata.
Solamente se puede acceder cada vez a un único elemento del fichero, que se denomina ventana del
fichero.
Dependiendo de cómo se desplaza la ventana por el fichero, podemos distinguir dos tipos de acceso:
- Acceso secuencial: La ventana del fichero sólo puede moverse hacia delante a partir del primer
elemento y siempre de uno en uno.
- Acceso directo: La ventana del fichero se puede situar directamente en cualquier posición del
fichero. Es un acceso similar al utilizado en los arrays.
El acceso directo suele ser más eficiente, ya que para leer un dato no hace falta leer antes todos los
anteriores.
La razón por la que existe el acceso secuencial es que existen dispositivos de memoria secundaria que
sólo admiten acceso secuencial (como por ejemplo las cintas). Además, el acceso secuencial se utiliza
también en dispositivos que admiten acceso directo cuando queremos leer los elementos de forma
secuencial, ya que este acceso es más sencillo. Por ello nosotros nos ocuparemos en este tema
exclusivamente de los ficheros secuenciales y no entraremos en ningun momento a estudiar los
ficheros de acceso directo.
Tipos de ficheros
En C/C++ existen básicamente dos tipos de ficheros, en función de la manera en que se guarda la
información dentro de ellosl: Los fichero de tipo texto y los ficheros binarios.
Ficheros de tipo texto
En los ficheros de tipo texto lo que guardaremos será la información en forma de caracteres, tal y
como se mostraría por pantalla. Por ejemplo, el valor entero ‘ 25 ’ se transformará en los caracteres ‘ 2 ’
y ‘ 5 ’.
Por este motivo las operaciones de escritura y lectura de ficheros de este tipo, serán similares a las
utilizadas para escribir en pantalla y leer de teclado.
Ficheros de tipo binario
La información se guarda en el fichero tal y como está en memoria, es decir, compuesta por unos y
ceros. Por ejemplo, el valor entero ‘ 25 ’ se guardará como ‘ 00011001 ’.
Procesamiento de un fichero
Siempre que queramos realizar cualquier operación con ficheros se debe seguir el siguiente esquema:
Apertura de Fichero → Operaciones → Cierre del fichero
Abrir fichero
En un lenguaje de programación, los ficheros son un tipo de dato más, y un fichero concreto se
referencia utilizando una variable de tipo fichero. Es lo que denominamos fichero lógico.
En C++ existen dos tipos de datos básicos para declarar ficheros:
ifstream // Para declarar ficheros de entrada (in)
ofstream // Para declarar ficheros de salida (out)
Para utilizar estos tipos hay que incluir antes el fichero de cabecera <fstream.h>.
Ejemplo:
ofstream f;
Esta sentencia nos declara una variable (fichero lógico) de tipo fichero de salida.
for (i = 0; i < 10; i++) fich << vec[i];
Fichero binario
Para escribir en ficheros de tipo binario se utiliza el metodo ‘write’ que escribe una cierta cantidad de
bits de información que están en la memoria del ordenador, en el fichero:
ref_a_fich .write ( dirección , tamaño_a_escribir );
Por ejemplo, si tenemos una variable ‘x’ de tipo real, y queremos guardar su valor en un fichero ‘fich’
de tipo binario sería:
fich.write ( (char *)(&x), sizeof (x) );
O si tenemos un vector ‘vec’ de 10 enteros:
fich.write ( (char )vec, sizeof (int) * 10);
Leer de fichero
Las funciones de lectura en ficheros se utilizan para recuperar información guardada en fichero y
ponerla en memoria para poder trabajar directamente con ella.
Al igual que en la escritura dependerá del tipo de fichero (si de texto o binario) las funciones son unas
u otras.
En cualquier caso, para poder leer información de un fichero, hay que saber exactamente cómo ha sido
guardada en él.
Fichero texto
Se lee como si leyésemos del teclado, pero indicando el fichero del que queremos leer la información.
ref_a_fichero >> caracter ; ref_a_fichero >> dato;
Para leer una frase completa se utiliza la función ‘getline’.
getline ( ref_a_fichero , cadena );
Por ejemplo, si quiero leer el valor real que he guardado anteriormente, en el ejemplo haría:
fich >> x;
O si queremos recuperar los 10 valores enteros del ejemplo:
for (i = 0; i < 10; i++) fich >> vec[i];
Fichero binario
La lectura es similar a la escritura pero utilizando el método ‘read’:
ref_a_fichero .read ( dirección , tamaño_a_leer );
Si queremos recuperar la información del real guardada en el ejemplo de escritura en ficheros binarios:
fich.read ( (char *)(&x), sizeof (x) );
O la información del vector:
fich.read (vec, sizeof (int) * 10);
Cerrar fichero
Una vez hemos terminado de utilizar los ficheros es conveniente cerrrarlos. La instrucción que
utilizaremos para cerrar el fichero será ‘close’:
ref_a_fichero .close ();
Otras instrucciones
Final de fichero -> ref_a_fichero. eof ();
Nos devuelve verdadero si estamos en el final de fichero. Falso en cualquier otro caso.
carácter EOF -> carácter final de fichero.
Lectura mediante get().
Si queremos leer el fichero carácter a carácter, lo más normal será utilizar el método get(), sin
embargo éste no devuelve cierto o falso para saber si se ha podido leer con éxito, puesto que tiene que
devolver el carácter que ha leído. La forma de leer un fichero con get() será por tanto ligeramente
distinta a la que hemos visto.
Ejemplo: Programa para leer los caracteres de un fichero y mostrarlos por pantalla.
#include<fstream.h> #include<iostream.h>
int main() { ifstream f; char dato;
f.open("datos.txt"); if(!f) cout << "Error abriendo el fichero" << endl; else { dato = f.get(); while(! f.eof()) { cout << dato << endl; dato = f.get(); } f.close(); } return 0; }
El método eof() es cierto si el dato que hemos leído era un final de fichero y falso en caso
contrario. Por esta razón hay que leer primero el carácter y después comprobar si hemos llegado a final
de fichero.
Ejemplo:
#include<fstream.h> #include<iostream.h>
struct Telefono { string nombre; string telefono; };
bool F_IntroTel (ifstream& f, Telefono& tel); void EscribeTel (Telefono tel);
int main(void) { Telefono tel; ifstream guia;
guia.open("guia.dat"); if(!guia) cout << "Error abriendo el fichero" << endl; else { while (!F_IntroTel(guia,tel)) EscribeTel(tel);
guia.close(); } return 0; }
bool F_IntroTel (ifstream& f, Telefono& tel) { getline(f,tel.nombre); getline(f,tel.telefono);
return (f.eof()); }
void EscribeTel (Telefono tel) { cout << tel.nombre << “\t” << tel.telefono << endl; }
Ejemplos de utilización de ficheros
Ejemplo: Realizar un programa que lea números enteros de un fichero de texto y guarde en un
segundo fichero de texto los que sean mayores de 20.
void main (void) { FILE *f, *g;
f = fopen ( “datos.dat”, “rt”); g = fopen (“salida.dat”, “wt”);
while (!feof (f) ) { fscanf (“%d”, &x); if (x > 20)
fprintf (“%d\n”, x); }
fclose (f); fclose (g); }
Ejemplo: Realizar un programa que lea números enteros de un fichero de binario y guarde en
un segundo fichero binario los que sean mayores de 20.
void main (void) { FILE *f, *g;
f = fopen ( “datos.dat”, “rb”); g = fopen (“salida.dat”, “wb”);
while (!feof (f) ) { fread (&x, sizeof (int), 1, f); if (x > 20) fwrite (&x, sizeof (int), 1, g); }
fclose (f); fclose (g); }
Ejemplo: Realizar un programa que lea caracteres de un fichero y cuente cuantas vocales de
cada clase encuentra en él. Guardar en dos ficheros, uno de texto y otro binario los resultados.
void main (void) { FILE *f_ent, *g_sal_bin, *g_sal_txt; char nom[15]; int num[5] = {0, 0, 0, 0, 0};
printf (“Dame nombre del fichero de entrada: “); fscanf (“%s”, nom); f_ent = fopen (nom, “rt”);
if (f_ent == NULL) { printf (“Error abriendo fichero %s para lectura\n”, nom); } else { ch = getc (f_ent); while (ch != EOF) { switch (ch) { case ‘a’: num[0]++; break; case ‘e’: num[1]++; break; case ‘i’: num[2]++; break; case ‘o’: num[3]++; break; case ‘u’: num[4]++; break; } }
g_sal_txt = fopen ( “salida.txt”, “wt”); if (g_sal_txt == NULL) printf (“Error abriendo fichero de texto para escritura.\n”);
Ejemplo: Programa para leer los 10 números del fichero y mostrarlos por pantalla.
#include<fstream.h> #include<iostream.h>
int main() { ifstream f; int i, dato;
f.open("datos.txt"); if(!f) cout << "Error abriendo el fichero" << endl; else { for(i = 1; i <= 10; i++) { f >> dato; cout << dato << endl; } f.close(); } return 0; }
Sin embargo, lo normal es que no sepamos cuantos elementos vamos a leer, sino que
queremos leer hasta que lleguemos al final del fichero. Para ello se puede utilizar un bucle
while de la siguiente forma:
while (f >> dato)
cout << dato << endl;
Cuando una instrucción para leer de fichero acaba con éxito, devuelve cierto , y cuando se produce
algún tipo de error (entre los que se incluye llegar al final del fichero), devuelve falso. De esta forma,
la instrucción anterior leerá, mientras sea posible, todos los números del fichero.
Ejemplo: Programa para leer los números de un fichero y mostrarlos por pantalla.
#include<fstream.h> #include<iostream.h> int main() { ifstream f; int dato;
f.open("datos.txt"); if(!f) cout << "Error abriendo el fichero" << endl; else { while(f >> dato) cout << dato << endl; f.close(); } return 0; }
Esta forma de leer del fichero se puede utilizar con cualquier tipo de lectura con >> y también con
getline.