sábado, 7 de agosto de 2010

UNIDAD 7
ARCHIVOS

7.1 CLASES DE E/S CLASE BASE ABSTRACTA


A menudo en el diseño, se quiere la clase base para presentar sólo una interfaz para sus clases derivadas. Esto es, se puede querer que nadie pueda crear un objeto de la clase base y que ésta sirva únicamente para hacer un upcast hacia ella, y poder tener una interfaz. Se consigue haciendo a la clase abstract (abstracta), poniendo como mínimo una función virtual pura. Se puede reconocer a una función virtual pura porque usa la palabra reservada virtual y es seguida por =0. Si alguien intenta hacer un objeto de una clase abstracta, el compilador lo impide. Esta es una utilidad que fuerza a un diseño en concreto.


Cuando se hereda una clase abstracta, hay que implementar todas las funciones virtuales, o la clase que hereda se convierte en una nueva clase abstracta. Crear una función virtual pura permite poner una función miembro en una interfaz sin forzar a proveer un cuerpo con código sin significado para esa función miembro. Al mismo tiempo, una función virtual fuerza a las clases que la hereden a que implemente una definición para ellas.

La clase base abstracta Stream es compatible con bytes de lectura y escritura. Stream tiene compatibilidad asincrónica. Sus implementaciones predeterminadas definen lecturas y escrituras asincrónicas según sus correspondientes métodos asincrónicos, y viceversa.
Todas las clases que representan secuencias se derivan de la clase Stream. La clase Stream y sus clases derivadas proporcionan una visión genérica de los orígenes de datos y los repositorios, aislando al programador de los detalles específicos del sistema operativo y sus dispositivos subyacentes.

7.2 REALIZAR ENTRADA Y SALIDA DE TEXTO


EN C:
En C un archivo puede ser cualquier cosa, desde un archivo de disco a un terminal o una impresora. Se asocia una secuencia con un archivo específico realizando una operación de apertura, una vez que está abierto, la información puede ser intercambiada entre éste y el programa. El puntero a un archivo es el hilo que unifica el sistema de E/S con buffer. Un puntero a un archivo es un puntero a una información que define varias cosas sobre él, incluyendo el nombre, el estado y la posición actual del archivo. En esencia, el puntero a un archivo identifica un archivo en disco específico y utiliza la secuencia asociada para dirigir el funcionamiento de las funciones de E/S con buffer. Para obtener una variable de tipo puntero a archivo se debe utilizar una sentencia como la siguiente:FILE *punt;

La función fopen() abre una secuencia para que pueda ser utilizada y le asocia a un archivo. Su prototipo es: FILE *fopen(const char *nombre_archivo, const char *modo); Donde nombre_archivo es un puntero a una cadena de caracteres que representan un nombre válido del archivo y puede incluir una especificación de directorio. La cadena que apunta modo determina cómo se abre el archivo.

Los modos son los siguientes:

r: Abre un archivo de texto para lectura.
w: Crea un archivo de texto par escritura
a: Abre un archivo de texto para añadir
r+: Abre un archivo de texto para lectura/escritura
w+: Crea un archivo de texto para lectura/escritura
a+: Añade o crea un archivo de texto para lectura/escritura


La función fclose() cierra una secuencia que fue abierta mediante una llamada a fopen(). Escribe toda la información que todavía se encuentre en el buffer del disco y realiza un cierre formal del archivo a nivel del sistema operativo. También libera el bloque de control de archivo asociado con la secuencia, dejándolo libre para su reutilización. A veces es necesario cerrar algún archivo para poder abrir otro, debido a la existencia de un límite del sistema operativo en cuanto al número de archivos abiertos. Su prototipo es: int fclose(FILE *fp);

La función putc() escribe caracteres en un archivo que haya sido abierto previamente para operaciones de escritura, utilizando la función fopen(). Su prototipo es: int putc(int car, FILE *pf);

La función getc() escribe caracteres en un archivo que haya sido abierto, en modo lectura, mediante fopen(). Su prototipo es: int getc(FILE *pf);La función fputs() escribe la cadena en la secuencia especificada. Su prototipo es: fputs() escribe la cadena en la secuencia especificada. Su prototipo es: int fputs(const char *cad, FILE *pf);La función fgets() lee una cadena de la secuencia especificada hasta que se lee un carácter de salto de línea o hasta que se han leído longitud-1 caracteres.

La función rewind() inicia el indicador de posición al principio del archivo indicado por su argumento. Su prototipo es: rewind() inicia el indicador de posición al principio del archivo indicado por su argumento. Su prototipo es: void rewind(FILE *pf);

Existen otras muchas funciones en la biblioteca estándar de C como pueden ser:

remove(): Borra el archivo especificado.
fflush(): Vacía el contenido de una secuencia de salida.
fread(): Lee tipos de datos que ocupan más de un byte. Permiten la lectura de bloques de cualquier tipo de datos.
fwrite(): Escribe tipos de datos que ocupan más de un byte. Permiten la escritura de bloques de cualquier tipo de datos.
fprintf(): Hace las funciones de printf() sobre un fichero.
fscanf(): Hace las funciones de scanf() sobre un fichero.
feof(): Detecta el final de un fichero.
ferror(): Detecta un error en la lectura/escritura de un fichero.
fclose(): cierra una secuencia que fue abierta mediante una llamada a fopen().
putc(): escribe caracteres en un archivo que haya sido abierto previamente para operaciones de escritura, utilizando la función fopen().
getc(): escribe caracteres en un archivo que haya sido abierto, en modo lectura, mediante fopen(). Su prototipo es:
fputs(): escribe la cadena en la secuencia especificada. Su prototipo es: int fputs(const char *cad, FILE *pf);
fgets(): lee una cadena de la secuencia especificada hasta que se lee un carácter de salto de línea o hasta que se han leído longitud-1 caracteres. Su prototipo es: fgets() lee una cadena de la secuencia especificada hasta que se lee un carácter de salto de línea o hasta que se han leído longitud-1 caracteres. Su prototipo es:int fgets(char *cad, FILE *pf);


EN C++:
Cómo podemos trabajar con un stream simultáneamente en entrada y salida. Para eso usaremos la clase fstream, que al ser derivada de ifstream y ofstream, dispone de todas las funciones necesarias para realizar cualquier operación de entrada o salida.
Hay que tener la precaución de usar la opción ios::trunc de modo que el fichero sea creado si no existe previamente.
#include
using namespace std;

int main() {
char l;
long i, lon;
fstream fich("prueba.dat", ios::in
ios::out ios::trunc ios::binary);

fich << "abracadabra" << lon =" fich.tellg();" i =" 0L;">
fich.seekg(i, ios::beg); fich.get(l); if(l == 'a')
{
fich.seekp(i, ios::beg); fich << 'e';
}
}
cout << "Salida:" << i =" 0L;">
{

fich.get(l); cout <<>

}

cout <<>
cin.get();
return 0;
}

Este programa crea un fichero con una palabra, a continuación lee todo el fichero e cambia todos los caracteres 'a' por 'e'. Finalmente muestra el resultado. Básicamente muestra cómo trabajar con ficheros simultáneamente en entrada y salida.

7.3 LEER Y ESCRIBIR ARCHIVOS

Leer archivos: Ifstream
Proporciona una interfaz para leer datos de archivos como flujos de entrada.

Los objetos de esta clase tratan de mantener internamente un puntero a un objeto filebuf que se pueden obtener llamando a rdbuf miembros.

El archivo que se asocia con la corriente puede ser especificado como un parámetro en el constructor o llamando a los miembros abierta.

Después de todas las operaciones necesarias en un archivo se han realizado, puede ser cerrado (o disociada) llamando a cerrar miembros. Una vez cerrado, el mismo objeto de secuencia de archivo puede ser usado para abrir otro archivo.

El is_open función miembro puede ser usado para determinar si el objeto de secuencia está asociada con un archivo.

Escribir archivos: Ofstream

Proporciona una interfaz para escribir datos en archivos como los flujos de salida.

Los objetos de esta clase de mantener internamente un puntero a un objeto filebuf que se pueden obtener llamando a rdbuf miembros.

El archivo que se asocia con la corriente puede ser especificado como un parámetro en el constructor o llamando a los miembros abierta.

Después de todas las operaciones necesarias en un archivo se han realizado, puede ser cerrado (o disociada) llamando a cerrar miembros. Una vez cerrado, el mismo objeto de secuencia de archivo puede ser usado para abrir otro archivo.

El is_open función miembro puede ser usado para determinar si el objeto de secuencia está asociada con un archivo.

7.4 REALIZAR ENTRADA Y SALIDA BINARIA

Muchos sistemas operativos distinguen entre ficheros de texto y ficheros binarios. Por ejemplo, en MS-DOS, los ficheros de texto sólo permiten almacenar caracteres. En otros sistemas no existe tal distinción, todos los ficheros son binarios. En esencia esto es más correcto, puesto que un fichero de texto es un fichero binario con un rango limitado para los valores que puede almacenar. En general, usaremos ficheros de texto para almacenar información que pueda o deba ser manipulada con un editor de texto. Un ejemplo es un fichero fuente C++.
Los ficheros binarios son más útiles para guardar información cuyos valores no estén limitados. Por ejemplo, para almacenar imágenes, o bases de datos. Un fichero binario permite almacenar estructuras completas, en las que se mezclen datos de cadenas con datos numéricos. En realidad no hay nada que nos impida almacenar cualquier valor en un fichero de texto, el problema surge cuando se almacena el valor que el sistema operativo usa para marcar el fin de fichero en un archivo de texto. En MS-DOS ese valor es 0x1A. Si abrimos un fichero en modo de texto que contenga un dato con ese valor, no nos será posible leer ningún dato a partir de esa posición. Si lo abrimos en modo binario, ese problema no existirá. Los ficheros que hemos usado en los ejemplos anteriores son en modo texto, veremos ahora un ejemplo en modo binario:

#include
#include
struct tipoRegistro {
char nombre[32];
int edad;
float altura;
};

int main() {
tipoRegistro pepe;
tipoRegistro pepe2;
ofstream fsalida("prueba.dat",
ios::out ios::binary);

strcpy(pepe.nombre, "Jose Luis");
pepe.edad = 32;
pepe.altura = 1.78;

fsalida.write(reinterpret_cast(&pepe),
sizeof(tipoRegistro));
fsalida.close();

ifstream fentrada("prueba.dat",
ios::in ios::binary);

fentrada.read(reinterpret_cast(&pepe2),
sizeof(tipoRegistro));
cout <<>fentrada.close();

cin.get();
return 0;
}

Al declarar streams de las clases ofstream o ifstream y abrirlos en modo binario, tenemos que añadir el valor ios::out e ios::in, respectivamente, al valor ios::binary. Esto es necesario porque los valores por defecto para el modo son ios::out e ios:in, también respectivamente, pero al añadir el flag ios::binary, el valor por defecto no se tiene en cuenta.


Cuando trabajemos con streams binarios usaremos las funciones write y read. En este caso nos permiten escribir y leer estructuras completas.


En general, cuando usemos estas funciones necesitaremos hacer un casting, es recomendable usar el operador "reinterpret_cast".


BIBLIOGRAFIA
http://www.tutoriales.itsa.edu.mx/programacion1/index.php?mod=clasesdees&ban=0











No hay comentarios:

Publicar un comentario