Manipular ficheros con iostream
es mucho más fácil y seguro
que usar stdio
en C. Todo lo que tiene que hacer es crear un objeto - el
constructor hace el trabajo. No necesita cerrar el fichero explícitamente (aunque puede,
usando la función miembro close()
) porque el destructor lo cerrará cuando
el objeto salga del ámbito. Para crear un fichero que por defecto sea de entrada, cree un objeto
ifstream
. Para crear un fichero que por defecto es de salida, cree un
objeto ofstream
. Un fstream
puede hacer ambas cosas.
Las clases de stream
de fichero encajan dentro de las clases iostream
como
se muestra en la siguiente figura:
Como antes, las clases que usted usa en realidad son especializaciones de
plantillas definidas por definiciones de tipo. Por ejemplo, ifstream
,
que procesa ficheros de char
, es definida como:
typedef basic_ifstream<char> ifstream;
Aqui tiene un ejemplo que muestra algunas de las características discutidas antes. Nótese que la inclusión de <fstream> para delarar las clases de fichero de E/S. Aunque en muchas plataformas esto también incluye <iostream> automáticamente, los compiladores no están obligados a hacer esto. Si usted quiere compatibilidad, incluya siempre ambas cabeceras.
//: C04:Strfile.cpp // Stream I/O with files; // The difference between get() & getline(). #include <fstream> #include <iostream> #include "../require.h" using namespace std; int main() { const int SZ = 100; // Buffer size; char buf[SZ]; { ifstream in("Strfile.cpp"); // Read assure(in, "Strfile.cpp"); // Verify open ofstream out("Strfile.out"); // Write assure(out, "Strfile.out"); int i = 1; // Line counter // A less-convenient approach for line input: while(in.get(buf, SZ)) { // Leaves \n in input in.get(); // Throw away next character (\n) cout << buf << endl; // Must add \n // File output just like standard I/O: out << i++ << ": " << buf << endl; } } // Destructors close in & out ifstream in("Strfile.out"); assure(in, "Strfile.out"); // More convenient line input: while(in.getline(buf, SZ)) { // Removes \n char* cp = buf; while(*cp != ':') ++cp; cp += 2; // Past ": " cout << cp << endl; // Must still add \n } } ///:~
Listado 5.5. C04/Strfile.cpp
La creación tanto del ifstream como del ofstream están seguidas de un
assure()
para garantizar que el fichero ha sido abierto
exitosamente. El objeto resultante, usado en una situación donde el compilador
espera un resultado booleano, produce un valor que indica éxito o fracaso.
El primer while
demuestra el uso de dos formas de la función
get()
. La primera toma los carácteres dentro de un buffer y pone
un delimitador cero en el buffer cuando bien SZ-1 carácteres han sido leidos o bien el
tercer argumento (que por defecto es '\n') es encontrado. La función get()
deja el carácter delimitador en el stream
de entrada, así que este
delimitador debe ser eliminado via in.get()
usando la forma de
get()
sin argumentos. Puede usar tambien la función miembro
ignore()
, que tiene dos parámetros por defecto. El primer argumento es el
número de carácteres para descartar y por defecto es uno. El segundo argumento es el carácter
en el que ignore()
se detiene (después de extraerlo) y por defecto es EOF.
A continuación, se muestran dos sentencias de salida
similares: una hacia cout
y la otra al
fichero de salida. Nótese la conveniencia aquí - no necesita
preocuparse del tipo de objeto porque las sentencias de
formateo trabajan igual con todos los objetos
ostream
. El primero hace eco de la
linea en la salida estándar, y el segundo escribe la línea
hacia el fichero de salida e incluye el número de línea.
Para demostrar getline()
, abra el fichero recién creado y quite los números de linea.
Para asegurarse que el fichero se cierra correctamente antes de abrirlo para la lectura, usted tiene dos
opciones. Puede envolver la primera parte del programa con llaves para forzar que el objeto out
salga del ámbito, llamando así al destructor y cerrando el fichero, que es lo que se hace aquí. Tambien puede l
lamar a close()
para ambos ficheros; si hace esto, puede despues rehusar el objeto de entrada
llamando a la función miembro open()
.
El segundo while
muestra como getline()
borra el caracter terminador
(su tercer argumento, que por defecto es '\n') del stream
de entrada cuando este
es encontrado. Aunque getline()
, como get()
, pone un cero en
el buffer, este todavía no inserta el carácter de terminación.
Este ejemplo, así como la mayoría de ejemplos en este capítulo, asume que cada llamada a alguna sobrecarga
de getline()
encontrará un carácter de nueva línea. Si este no es el caso, la estado
eofbit
del stream
será activado y la llamada a getline()
retornará falso, causando que el programa pierda la última línea de la entrada.