ARCHIVOS BINARIOS en C++ Los archivos archivos binarios binarios almacenan almacenan la información información “byte “byte a byte” byte” en lugar lugar de carácter por por carác arácte ter, r, esto esto es muy útil útil cuan cuando do se nece necesi sita ta alm almacen acenar ar o recu recupe pera rarr información que no es un texto, por ejemplo: una imagen, un archivo ejecutable, un objeto, o datos numéricos de punto flotante. Estos archivos no se pueden leer con cualquier editor de texto, como el block de notas, notas, hará hará falta falta otro otro progra programa ma,, que podría podría ser desarr desarroll ollado ado por nosotro nosotros s para para poder leerlo. Como ejemplo, realizaremos una copia de un archivo que contiene una imagen a otro archivo. archivo. Note que en este caso el programa programa ejecuta ejecuta operacion operaciones es en archivos archivos utilizando el modo binario (ios::binary ), ), además es necesario aclarar el modo de apertura o escritura (ios::in) o (ios::out )
Programa Program a para copiar una foto a otro archivo #include #include using namespace std; int main() { ifstream origen("foto.jpg", ios::binary); ofstream destino("CopiaFoto.jpg", ios::binary); // QUITE ios::b ios::binary inary y vea vea el resultado resultado
char byte;
while( !origen.eof() && !origen.fail() ) { origen.read((char *) & byte & byte,, sizeof(char sizeof(char)); ));
if (origen.good()) (origen.good()) { destino.write((char *) & byte & byte,, sizeof(char sizeof(char)); ));
} } destino.close(); origen.close(); return 0; }
Observará que se utiliza la función miembro origen.read ( ) para leer un byte del archivo especificado por el objeto origen. origen. En forma similar, se utiliza la función miembro destino.write ( ) para escribir un byte en el archivo especificado por el objeto destino, que crea el archivo llamado CopiaFoto. Un byte no es más que 8 bits bits y se lo puede guardar en una variable de tipo char. char.
Leer y escribir en un archivo binario Para leer y escribir a partir de la posición actual del cursor en el archivo binario, se debe utilizar las funciones read () y write (). archivo.read ((char *) &c, num); archivo.write ((char *) &c, num);
Donde c es una variable o un objeto de cualquier tipo por referencia (&) , y num es un entero que indica un número de bytes que se leerán o que se escribirán en el archivo. Normalmente, para expresar el tamaño o número de bytes a leer o escribir se usa la función sizeof que nos retorna el número de bytes que ocupa una variable o tipo. Por ejemplo, para agregar en un archivo binario dos variables de punto flotante al final del archivo se tiene: int e=10; float f=12.5235;
fstream archi("prueba.bin", ios::binary|ios::out|ios::app); archi. write((char *)& e, sizeof (int)); archi. write((char *)& f, sizeof (float)); archi.close(); Pero para poder leer los datos no basta con abrir el archivo, debe escribir un programa para poder leer los datos como se muestra a continuación: int x; float y;
fstream archi2("prueba.bin", ios::binary|ios::in); archi2.read((char *)& x, sizeof (int)); archi2. read ((char *)& y, sizeof (float)); archi2.close(); cout<< "Se leyeron x= "< #include using namespace std; int main() { gato Garfield (13, "Naranja"); gato Tom (3, "Plomo"); // Guardamos en el archivo los dos gatos
ofstream archivo("Datos.dat",ios::binary); archivo.write((char *)& Garfield, sizeof(gato)); archivo.write((char *)& Tom, sizeof(gato));
archivo.close(); // Leemos del archivo con el objeto gatin gato gatin;
ifstream archileer("Datos.dat",ios::binary); archileer.seekg(sizeof(gato)*1); //Posicionar en el segundo gato archileer.read((char *) & gatin, sizeof(gato));
gatin.mostrar(); //Posicionar al inicio del archivo archileer.seekg(0); archileer.read((char *) & gatin, sizeof(gato));
gatin.mostrar(); archileer.close(); }
Programa que escribe usando app y muestra TODO el archivo #include "gato.h" #include #include using namespace std; int main()
{ gato
Garfield (7,"Naranja");
// Guarda los datos usando app fstream archivo("Datos.bin",ios::binary|ios::out|ios:: app); archivo.write((char *)&Garfield, sizeof(gato));
archivo.close();
// Lee los datos de todo el archivo en gatin gato gatin; fstream archi2("Datos.bin",ios::binary|ios::in); archi2.seekg(0); while( !archi2.eof() ) { archi2.read((char *) &gatin, sizeof(gato));
if (!archi2.eof()) // Sin este if se muestra el ultimo 2 veces gatin.mostrar(); }
archi2.close(); }
Ejercicio:
Mejorar el anterior programa y permitir:
1. Mostrar todos los gatos rojos 2. Contar cuantos gatos tienen 7 vidas 3. Buscar todos los gatos que tienen entre 5 y 10 vidas y guardarlos en un segundo archivo
4. Cambiar el color a LILA del tercer gato introducido usar seekp ,ios::out y ios::in 5. A todos los gatos que tengan menos de 3 vidas sumarle una vida, use seekp 6. Buscar gatos negros con 13 vidas y cambiarlos (en el archivo) por un gato blanco con 7 vidas, use seekp
Usando una CLASE LISTA DE GATOS Si bien los archivos almacenan la información permanentemente, tienen la desventaja de que el tiempo de acceso a sus datos es más lento que el acceso a datos en la memoria principal, por ello dependiendo del problema, puede ser buena idea usar una LISTA para descargar los datos del archivo y procesarlos en un tiempo más corto. 7. Crear una clase lista de gatos y guardar en la LISTA a todos los gatos del archivo
8. Quitarles a todos los gatos de la lista una vida 9. Ordenar ascendentemente los gatos de la LISTA por el número de vidas 10. Guardar la LISTA ordenada en un segundo archivo