Anda di halaman 1dari 19

Fundamentos de Informtica

6- Ficheros 6.1. Introduccin a ficheros. 6.2. Operaciones con ficheros 6.3. Ficheros en C/C++.

6.3.1. Streams Ejemplo del uso de fstream: leer y escribir un artculo 6.3.2. Ficheros de estructuras

6.1. Introduccin a ficheros

Hasta ahora un programa poda almacenar informacin en la memoria mediante las variables declaradas (tipos elementales, estructuras, tablas). Este almacenamiento es temporal y est limitado al tiempo de ejecucin del programa.

Cuando surge la necesidad de almacenar informacin de manera permanente se deben usar ficheros. Un fichero es una entidad que contiene informacin de un conjunto de elementos. El fichero puede estar guardado en algn medio de almacenamiento secundario como por ejemplo disco rgido, disckette, etc. La agrupacin de ficheros relacionados entre s por algn concepto se denomina base de datos.

Existen algunas caractersticas a sealar:

Un fichero se identifica por su nombre, el cual generalmente est compuesto por:

Path: indica la ruta para encontrar el fichero incluyendo la unidad de almacenamiento donde se halla. Nombre Extensin: son tres caracteres que sirven para identificar el tipo de fichero

Ejemplo: "C:\Mis documentos\apuntes.doc"

Un fichero puede estar compuesto por registros, cada uno de los cuales contiene informacin sobre un elemento. Segn se vi en el captulo 5, seccin 5.2., un registro est compuesto por campos. Se denomina clave de acceso o identificador de registro al conjunto de campos mnimo que permite identificar de manera nica cada registro.

Ejemplo: se tiene un fichero de registros o estructuras Articulo

struct Articulo { int codigo; char descripcion[maxdesc]; float precio; };

La clave de acceso de cada registro es el campo codigo, pues dado un cdigo en particular se puede identificar un nico registro. En cambio, el campo precio no sirve como clave de acceso pues puede existir ms de un artculo con el mismo precio.

El modo de acceso a los datos de un fichero puede ser de dos tipos:

Secuencial: para acceder al elemento i-simo se recorre desde el primer elemento hasta el elemento i-1.

Ejemplo: el almacenamiento en una cinta es de acceso secuencial.

Directo: para acceder al elemento i-simo se hace directamente.

Ejemplo: el almacenamiento en un disco es de acceso directo.

El modo de organizacin lgica de los datos de un fichero puede ser de tres maneras:

Secuencial: las consultas de los registros se hace secuencialmente desde el primer elemento hasta el elemento i-simo. La alta de un nuevo registro se realiza al final del fichero.

Directa: se establece una relacin entre la clave del registro y la posicin del registro en el fichero. Para acceder al elemento i-simo se aplica una funcin de acceso que calcula la posicin del registor en el fichero de acuerdo a la clave del mismo.

Ejemplo: se tiene un fichero de registros Articulo cuyo campo clave es el cdigo. Los cdigos son numeros que van de 10 en 10, ej. 10, 20, 30, 40, 50, etc. Se realiza la siguiente funcin de acceso F: F (cdigo) = cdigo / 10; la cual que devuelve la posicin del registro a partir del cdigo, y por lo tanto puede accederse a l directamente.

Indexada: bsicamente es una organizacin secuencial a la que se le agrega una o ms tablas de ndices que permiten acceder a los registros de manera ms directa.

Ejemplo: se tiene un fichero de registros Articulo cuyo campo clave es el cdigo. Los cdigos son numeros que no siguen un orden determinado, por lo tanto no se puede construir una funcin de acceso directo. Se construye una tabla de ndices que permite acceder directamente a los registros cuyo cdigo se encuentra en un rango dado. Si se desea buscar los registros mediante parte de su descripcin, se puede construir otra tabla de ndices que permita, por ejemplo, acceder a todos los registros cuya descripcin comienza con una letra o una serie de letras dadas.

6.2. Operaciones con ficheros

Existen operaciones que afectan a todo el fichero, entre las cuales se enumeran:

Crear un fichero Borrar un fichero Ordenar un fichero segn algn criterio de orden Fusionar dos ficheros para formar un tercer fichero Dividir un fichero en dos o ms ficheros

Adems, existen otras operaciones que afectan a uno o ms registros del fichero, entre las cuales se enumeran:

Alta de un nuevo registro Baja de un registro Modificacin de uno o ms registros Consulta de uno o m registros

6.3. Ficheros en C/C++

6.3.1. Streams

Existe una manera de manipular ficheros en C++ mediante los denominados streams.

Un stream representa un flujo de informacin:

desde el programa a un dispositivo o perifrico de salida, o desde un perifrico de entrada al programa

La manera de utilizar un stream de entrada es:

stream_entrada >> variable;

La manera de utilizar un stream de salida es:

stream_salida << informacin;

Hasta el momento se han utilizado dos streams predefinidos:

cin es un stream de entrada asociado al teclado cout es un stream de salida asociado a la pantalla

Pueden definirse stream de entrada y/o salida y asociarlos a un fichero, de manera que se puedan recibir datos del fichero y/o enviar datos al fichero respectivamente.

La librera que se debe utilizar es <fstream.h>.

Se debe declarar un stream mediante el constructor:

fstream nombre_stream (nombre_fichero, opciones);

Los parmetros son optativos. Si estn presentes sirven para realizar la apertura del fichero. El nombre del fichero es un string que indica la ruta del fichero que se asocia al stream.

Las opciones indican diferentes modos entre los cuales se encuentran:

ios::in: crea un stream de entrada, es decir, para lectura de datos del fichero ios::out: crea un stream de salida, es decir, para escritura de datos en el fichero ios::ate: hace que la posicin inicial sea al final del fichero ios::app: se sita al final del fichero antes de cada escritura ios::trunc: borra cualquier cosa que pudiera haber en el fichero ios::nocreate: si el fichero no existe fallar ios::noreplace: si el fichero existe fallar ios::bin: abre el fichero como binario

Estas opciones pueden combinarse mediante el operador | .

Ejemplo:

/* stream de salida asociado al fichero prueba.txt. Se borra cualquier contenido del mismo */ fstream fichero1 ("prueba.txt", ios::out|ios::trunc); /* Slo es vlido realizar escrituras dado que el stream es de salida*/ int i := ... ; // por ej. para escribir el valor de un entero fichero1 << i;

Ejemplo: /* stream de entrada asociado al fichero prueba.txt */ fstream fichero2 ("prueba.txt", ios::in); /* Slo es vlido realizar lecturas dado que el stream es de entrada*/ int i; // por ej. para leer el valor de un entero fichero2 >> i;

Existen diferentes operaciones que pueden realizarse con un fstream usando la siguiente sintaxis:

nombre_fstream.operacion

Entre las operaciones disponibles se encuentran:

open(nombre_fichero, opciones), con los mismos parmetros que el constructor. Puede usarse cuando en el constructor se ignor la apertura del fichero.

Ejemplo: fichero1.open("prueba.txt", ios::in); // antes de realizar cualquier lectura

close(), cuando se desea cerrar un stream

Ejemplo: fichero1.close(); // despues de haber realizado todas las lecturas y/o escrituras

eof(), es una funcin que devuelve un valor diferente a 0 (TRUE) si se lleg al fin de fichero, de otro modo devuelve 0 (FALSE)

Ejemplo: if (fichero1.eof()){ //fin de fichero, no hay ms datos }

is_open() es una funcin que devuelve un valor diferente a 0 (TRUE) si el fichero asociado al stream est abierto, de otro modo devuelve 0 (FALSE).

Ejemplo: if (fichero1.is_open()){ //el fichero est abierto }

Se debe considerar que para leer o escribir un stream existe un "cabezal" que se posiciona en el lugar a realizar la operacin. Las siguientes funciones informan la posicin o manipulan el cabezal.

tellp(), es una funcin que devuelve como resultado la posicin actual (tipo pos_type) de un stream de salida seekp(posicin, posicin_inicial), sita el lugar de escritura indicada en posicin en forma relativa a posicion_inicial, la cual puede ser ios::beg (comienzo), ios::cur (actual), ios::end (fin).

Ejemplo del uso de fstream: leer y escribir un artculo

6.3.2. Ficheros de estructuras

Cuando se quiere guardar informacin de estructuras o registros en C/C++ se deben utilizar las funciones de ficheros de la librera <stdio.h>.

Existe un tipo de datos denominado FILE por medio del cual se manipulan los ficheros.

Entre las funciones definidas para trabajar con ficheros se encuentran:

FILE* fopen (const char *name, const char *mode)

La funcin fopen recibe como parmetros: un string name con el nombre del fichero un string mode con el modo de apertura del fichero que puede ser:

"r" : abre fichero existente para lectura. Si no existe falla la operacin "w" : abre fichero para escritura. Si existe, sus contenidos se borran. "a" : abre fichero para escritura. Si existe, se agregan los datos al final "r+" : abre fichero para lectura y escritura. El fichero debe existir. "w+" : abre fichero para lectura y escritura. Si existe, sus contenidos se borran

"a+" : abre fichero para lectura y escritura. Si existe, se agregan datos al final Devuelve un puntero a un fichero, que en caso de error en la operacin ser NULL.

int fclose (FILE *file)

La funcin fclose cierra el fichero abierto file. Devuelve un int que si es 0 indica que la operacin se realiz con xito.

size_t fread (void *pbuffer, size_t size, size_t number, FILE *file)

La funcin fread se usa para leer desde el fichero, y recibe como parmetros:

un puntero a FILE del fichero file desde el cual se quiere leer un nmero number de tipo size_t que indica la cantidad de elementos que se quiere leer un nmero size de tipo size_t que indica el tamao en bytes de cada elemento un puntero pbuffer a un lugar donde se copiarn los elementos ledos. Considerar que el tamao que debe tener el buffer apuntado por pbuffer tiene que se lo suficientemente grande como para albergar la cantidad de elementos indicada.

Devuelve un nmero de tipo size_t que indica el nmero de elementos que se han ledo.

size_t fwrite (void *pbuffer, size_t size, size_t number, FILE *file)

La funcin fwrite se usa para escribir en el fichero, y recibe los mismos parmetros que la funcin fread.

Devuelve un nmero de tipo size_t que indica el nmero de elementos que se han escrito.

int fseek (FILE *file, long offset, int mode)

La funcin fseek desplaza el cabezal de lectura, y recibe los parmetros: un long offset que indica la cantidad de bytes que se desplaza un int mode que indica desde dnde se desplaza, con uno de los siguientes valores:

SEEK_SET: desde el comienzo SEEK_CUR: desde el cursor SEEK_END: desde el final Devuelve un int que si es 0 indica que la operacin se realiz con xito.

int ftell (FILE *file)

La funcin ftell devuelve un int que indica el nmero de bytes desde el comienzo hasta la posicin donde se encuentra el cabezal de lectura.

int feof (FILE *file)

Luego del primer intento de lectura ms all de la seal de fin de fichero, la funcin feof devuelve un valor diferente de 0. Devuelve 0 mientras las lecturas hehcas no lleguen al final del fichero.

void rewind (FILE *file)

La funcin rewind sita el cabezal de lectura al inicio del fichero.

Cabe destacar que tanto las funciones fread, fwrite, fseek, ftell manejan posiciones o tamaos indicados en bytes. Para obtener el tamao en bytes de una estructura dada puede usarse la funcin

sizeof (estructura)

y con este valor pueden calcularse los parmetros necesarios de las funciones anteriores.

Ejemplo: Crear un fichero de artculos. Se debe permitir agregar artculos, modificar un artculo existente y listar todos los artculos existentes.

#include <iostream.h> #include <stdio.h>

const int maxart = 100; const int maxdesc = 30;

struct articulo {

int codigo; char descripcion[maxdesc]; float precio;

};

// La funcin mostrararticulo muestra por pantalla un artculo dado

// Implementada en el captulo 5 void mostrararticulo (struct articulo art);

// La funcin leerarticulo permite introducir por teclado los datos de un artculo // Implementada en el captulo 5 struct articulo leerarticulo ();

struct articulo leerarticulo (int codigo){ //Asigna el codigo al articulo y permite al usuario introducir el resto de los campos

struct articulo art; art.codigo = codigo; leerdescripcion(art.descripcion); leerprecio(art.precio); return art;

void copiararticulo(struct articulo art_origen, struct articulo *part_destino){ // Esta funcion copia los datos del articulo art_origen en el articulo apuntado por el puntero part_destino // Notar: dado que ha sido pasado el puntero no se debe pasar por referencia el parmetro. Si en cambio, se hubiera pasado una estructura debera haber sido por referencia, es decir, struct articulo &art_destino

part_destino ->codigo = art_origen.codigo; part_destino ->precio = art_origen.precio;

for (int i=0;i<maxdesc;i++){ part_destino->descripcion[i] = art_origen.descripcion[i]; }

void ListarElementos(char *nombre) {

FILE *f; struct articulo art;

// El fichero se abre slo para lectura y se espera que exista f = fopen (nombre, "r"); if (f != NULL){ fread (&art, sizeof(struct articulo), 1, f); while (!feof(f)){ // la condicin equivale a (feof(f) != 0) mostrararticulo(art); fread (&art, sizeof(struct articulo), 1, f); } fclose (f); } else cout << "Error de apertura del fichero";

int BuscarArticulo (char *nombre, struct articulo *art){ // Esta funcin busca en el fichero la existencia de un registro con codigo igual al del articulo apuntado por art

// Si lo encuentra devuelve la posicin en bytes del registro y copia el resto de los datos en la estructura apuntada por art // Si no se encuentra, devuelve -1

int posicion = -1; FILE *f; struct articulo art_actual;

// El fichero se abre slo para lectura y se espera que exista f = fopen (nombre, "r"); if (f != NULL){ bool encuentra = false; fread (&art_actual, sizeof(struct articulo), 1, f); while (!feof(f) && !encuentra){ // !feof(f) equivale a (feof(f) != 0) if (art_actual.codigo == art->codigo){ encuentra = true; posicion = ftell (f) - sizeof(struct articulo); copiararticulo(art_actual, art); } else{ fread (&art_actual, sizeof(struct articulo), 1, f); } } fclose (f); } else cout << "Error de apertura del fichero"; return posicion;

void BuscarElemento(char *nombre){

struct articulo art; art.codigo = leercodigo ();

int posicion = BuscarArticulo (nombre, &art); if (posicion >= 0){ // Existe un articulo con ese codigo mostrararticulo (art); } else{ cout << "no existe ningn elemento con ese cdigo"<< endl; }

void InsertarElemento(char *nombre){

struct articulo art; art = leerarticulo ();

int posicion = BuscarArticulo (nombre, &art); if (posicion >= 0){ // Existe un articulo con ese codigo cout << "existe articulo con ese cdigo" << endl; mostrararticulo (art); } else{ // El fichero se abre para escritura al final del mismo. Si no existe se crea

FILE *f = fopen (nombre, "a+"); if (f != NULL){ fwrite (&art, sizeof(struct articulo), 1, f); fclose (f); } else{ cout << "Error de apertura del fichero"; } }

void ModificarElemento(char *nombre){

struct articulo art_old, art_new; leercodigo (art_old.codigo);

int posicion = BuscarElemento (nombre, &art_old); if (posicion >= 0){ // Existe un articulo con ese codigo en la posicion // El fichero se abre para escritura pero se espera que exista FILE *f = fopen (nombre, "r+"); if (f != NULL){ mostrararticulo (art_old); art_new = leerarticulo(art_old.codigo); fseek(f, posicion, SEEK_SET); fwrite (&art_new, sizeof(struct articulo), 1, f); fclose (f); } else cout << "Error de apertura del fichero"; }

else { cout << "No existe ningn articulo con ese cdigo" << endl; }

void CrearFichero (char *nombre){

FILE *f = fopen (nombre, "w"); fclose (f);

void main (int argc, char **argv){

// si hay ms de un argumento se asume que es el nombre del fichero sino se indicaron argumentos se usa el nombre del // fichero por defecto char *nombre_fichero = "articulos.dat"; if (argc > 1){ nombre_fichero = argv[1]; }

bool terminar = false; char opcion;

while ( !terminar){

opcion = leeropcion(); switch (opcion){ case 'C': CrearFichero(nombre_fichero); break; case 'L': ListarElementos(nombre_fichero); break; case 'I': InsertarElemento(nombre_fichero); break; case 'B': BuscarElemento(nombre_fichero); break; case 'M': ModificarElemento(nombre_fichero); break; }} case 'T': terminar = true;

La funcin leeropcion() muestra un men con 6 opciones: (C)rear fichero, (L)istar elementos, (I)nsertar elemento, (B)uscar elemento, (M)odificar elemento, (T)erminar y retorna una eleccin vlida introducida por el usuario.

Anda mungkin juga menyukai