Ficheros
El manejo de ficheros desde C++ puede llegar a ser casi tan sencillo como el manejo de la entrada y salida estándar (pantalla y teclado), con la diferencia de que abrimos el fichero (open) antes de trabajar con él y lo cerramos (close) al terminar. Por ejemplo, para escribir una frase en un fichero de texto (que se crearía automáticamente), podríamos usar un fichero de salida (ofstream), así:
​
​
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream ficheroSalida;
ficheroSalida.open ("ficheroTexto.txt");
ficheroSalida << "Texto para el fichero";
ficheroSalida.close();
return 0;
}
​
Si lo que queremos es leer una línea de un fichero, sería muy similar, pero usaríamos ifstream en vez de ofstream, y, si la línea que leemos puede contener espacios (es lo habitual), usaremos getline en vez de >>, al igual que hacíamos con la entrada desde teclado:
​
​
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ifstream ficheroEntrada;
string frase;
ficheroEntrada.open ("ficheroTexto.txt");
getline(ficheroEntrada, frase);
ficheroEntrada.close();
​
cout << "Frase leida: " << frase << endl;
return 0;
}
Por supuesto, la situación da mucho más juego. Por ejemplo, no necesariamente querremos sólo leer de un fichero, o sólo crearlo: podemos querer añadir al final de un fichero que ya existe, o modificar cualquier posición intermedia del fichero, o abrir un fichero de forma que podamos tanto leer de él como escribir en él. Para esas cosas, en vez de usar ofstream o ifstream usaremos un tipo de fichero más genérico, el fstream, que nos permite indicar el modo de apertura (lectura o escritura, texto o binario, etc), con los siguientes "flags" predefinidos:
​
ios::in
Abrir para entrada (lectura)
ios::out
Abrir para salida (escritura)
ios::binary
Abre en modo binario
ios::ate
​
Escoge el final del fichero como posición inicial (si no se dice lo contrario, la posición inicial al abrir el fichero sería el comienzo del fichero)
ios::app
Abrir para añadir (append) al final, sólo
utilizable si se ha abierto el fichero
exclusivamente para escritura
ios::trunc
Trunca el fichero si existía, borrando todo su contenido anterior
​
Archivos binarios
Hemos visto lo básico del manejo de ficheros de texto, pero también es frecuente tener que manejar ficheros "binarios", que contengan cualquier tipo de información, estructurada o no.
Tendremos funciones para saltar a una cierta posición, para saber en qué posición del fichero nos encontramos, para guardar todo un bloque de datos o para leer todo un bloque de datos.
Primero vamos a resumirlas y luego veremos un ejemplo de su uso:
Para saltar una una cierta posición usaremos "seekg" si el fichero es de lectura ("seek" = buscar, g = abreviatura de "get", lectura) o bien "seekp" si el fichero es de escritura (la "p" proviene de "put").
En estos saltos deberemos indicar la cantidad de espacio que queremos saltar, y desde qué punto (el principio del fichero se indica como "ios::beg", la posición actual como "ios::cur", y el final como "ios::end"), así:
fichero.seekg(10, ios::cur); // Saltar 10 bytes
fichero.seekg(0, ios::beg); // Volver al principio
fichero.seekg(0, ios::end); // Ir al final del fichero
Para saber en qué posición estamos usaremos "tellg" (para lectura de ficheros) o "tellp" (para escritura en fichero). Si lo hacemos cuando estamos al final del fichero, podremos saber cual es la longitud en bytes de dicho fichero:
fichero.seekg(0, ios::end); // Ir al final del fichero
tamanyo = fichero.tellg(); // Ver posicion para saber tamaño
​
Para leer un bloque de información usaremos "fichero.read(bloque, tamaño);" y para escribir un bloque "fichero.write(bloque, tamaño);".
Vamos a ver un ejemplo que compruebe si existe información almacenada en un fichero MP3 (lo que se conoce como el "Id3 tag", y que puede contener autor, canción, álbum...) :
​
#include <iostream>
#include <fstream>
using namespace std;
int main () {
fstream ficheroMp3;
char marca[3];
ficheroMp3.open ("ejemplo.mp3", ios::in | ios::binary);
// Compruebo si he podido abrir
if (ficheroMp3.is_open()) {
// Me coloco donde empieza el ID3 TAG
ficheroMp3.seekg(-128, ios::end);
// Leo 3 bytes
ficheroMp3.read(marca, 3);
// Digo si day datos o no
if ((marca[0] != 'T') || (marca[1] != 'A') || (marca[2] != 'G'))
cout << "Sin datos de artista" << endl;
else
cout << "Parece un MP3 con ID3 TAG" << endl;
// Finalmente, cierro
ficheroMp3.close();
}
// Si no he podido abrir, aviso
else cout << "Fichero inexistente" << endl;
return 0
}