Sei sulla pagina 1di 6

Manejo de archivos en C++ Entrada/Salida de archivos Trataremos los principales aspectos de las operaciones de E/S en archivos.

Operaciones de escritura en archivos


El archivo de cabecera fstream.h define las clases ifstream, ostream y fstream para operaciones de lectura, escritura y lectura/escritura en archivos respectivamente. Para trabajar con archivos debemos crear objetos de stas clases de acuerdo a las operaciones que deseamos efectuar. Empezamos con las operaciones de escritura, para lo cual bsicamente declaramos un objeto de la clase ofstream, despus utilizamos la funcin miembro open para abrir el archivo, escribimos en el archivo los datos que sean necesarios utilizando el operador de insercin y por ltimo cerramos el archivo por medio de la funcin miembro close, ste proceso est ilustrado en nuestro primer pro!rama, archiv"#.cpp.

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // archiv"#.cpp // %emuestra la escritura bsica en archivo //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'fstream.h( int main)* + ofstream archivo, // objeto de la clase ofstream archivo.open)-datos.t.t-*, archivo '' -Primera l/nea de te.to- '' endl, archivo '' -0e!unda l/nea de te.to- '' endl, archivo '' -1ltima l/nea de te.to- '' endl, archivo.close)*, return ", 2
En el pro!rama se ha creado un objeto de la clase ofstream llamado archivo, posteriormente se utiliza la funcin miembro open para abrir el arcivo especificado en la cadena de te.to que se encuentra dentro del parntesis de la funcin. Podemos invocar a la funcin constructora de clase de tal manera que el archivo tambin se puede abrir utilizando la si!uiente instruccin3 ofstream archivo)-datos.t.t-*, // constructora de ofstream 4aturalmente, al utilizar la funcin constructora ya no es necesario utilizar la funcin miembro open, sta forma de abrir un archivo es preferida porque el cdi!o es ms compacto y fcil de leer. %e la misma forma que se utilizan manipuladores de salida para modificar la presentacin en pantalla de los datos del pro!rama, i!ual es posible utilizar stos manipuladores al escribir datos en un archivo como lo demuestra el pro!rama archiv"5.cpp, observe que se utiliza un constructor para crear y abrir el archivo llamado %atos.t.t3

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // archiv"5.cpp // %emuestra el uso de manipuladores //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'iostream.h( &include 'fstream.h( &include 'iomanip.h( int main)* + ofstream archivo)-%atos.t.t-*, // constructor de ofstream int numero, cout '' -6ntroduzca un numero3- '' endl, cin (( numero, archivo '' -El valor introducido en base #" es3 - '' numero '' endl, archivo '' resetiosfla!s)ios33dec*, archivo '' setiosfla!s)ios33oct*, archivo '' -en base octal es3 - '' numero '' endl, archivo '' resetiosfla!s)ios33oct*, archivo '' setiosfla!s)ios33he.*, archivo '' -y en base he.adecimal es3 - '' numero '' endl, archivo '' setiosfla!s)ios33uppercase7ios33sho8base*, archivo '' -utilizando los manipuladores uppercase y sho8base'' - el valor es3 - '' numero '' endl, archivo '' resetiosfla!s)ios33uppercase7ios33sho8base*, archivo '' resetiosfla!s)ios33he.*, archivo '' setiosfla!s)ios33sho8pos7ios33sho8point7ios33fi.ed*,

archivo '' -9tilizando los manipuladores sho8pos,- '' - sho8point y fi.ed3 - '' )float*numero '' endl, archivo '' resetiosfla!s)ios33sho8pos7ios33sho8point7ios33fi.ed*, archivo '' -:inalmente el valor es - '' numero '' endl, archivo.close)*, return ", 2 Modos de apertura de archivo
;l especificar la apertura de un archivo como se ha mostrado en los pro!ramas anteriores, el pro!rama sobreescribe cualquier archivo e.istente llamado %atos.t.t en el directorio de trabajo del pro!rama. %ependiendo del propsito del pro!rama es posible que sea necesario a!re!ar datos a los ya e.istentes en el archivo, o quiz sea necesario que las operaciones del pro!rama no se lleven a cabo en caso de que el archivo especificado e.ista en el disco, para stos casos podemos especificar el modo de apertura del archivo incluyendo un parmetro adicional en el constructor, cualquiera de los si!uientes3 < ios33app =peraciones de a>adidura. < ios33ate ?oloca el apuntador del archivo al final del mismo. < ios33in =peraciones de lectura. Esta es la opcin por defecto para objetos de la clase ifstream. < ios33out =peraciones de escritura. Esta es la opcin por defecto para objetos de la clase ofstream. < ios33nocreate 0i el archivo no e.iste se suspende la operacin. < ios33noreplace ?rea un archivo, si e.iste uno con el mismo nombre la operacin se suspende. < ios33trunc ?rea un archivo, si e.iste uno con el mismo nombre lo borra. < ios33binary =peraciones binarias. %e esta manera, podemos modificar el modo de apertura del pro!rama archiv"5.cpp para que los datos del pro!rama se concatenen en el archivo %atos.t.t simplemente escribiendo el constructor as/3 ofstream archivo)-%atos.t.t-, ios33app*,. 0i deseamos que el pro!rama no sobreescriba un archivo e.istente especificamos el constructor de sta manera3 ofstream archivo)-%atos.t.t-, ios33noreplace*,. 9tilizando los especificadores de modo de apertura se puede conse!uir un mayor control en las operaciones de E/0 en archivos.

Operaciones de lectura de archivos


Para abrir un archivo y realizar operaciones de lectura se crea un objeto de la clase ifstream y se procede prcticamente de la misma forma que lo e.puesto en el apartado anterior. %espus de abrir el archivo se puede leer su contenido utilizando las funciones miembro de la clase ifstream o bin el operador de e.traccin. ?uando se lee un archivo, por lo !eneral se empieza al principio del mismo y se leer su contenido hasta que se encuentre el final del archivo. Para determinar si se ha lle!ado al final del archivo se puede utilizar la funcin miembro eof como condicin de un bucle 8hile. ;dems se puede utilizar la funcin miembro fail para detectar un error al abrir el archivo, esto se demuestra en el si!uiente pro!rama, archiv"@.cpp3

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // archiv"@.cpp // %emuestra operaciones de lectura de archivos //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'fstream.h( int main)* + ifstream archivo)-Pruebas.t.t-, ios33noreplace*, char lineaA#5BC, lon! contador D "E, if)archivo.fail)** cerr '' -Error al abrir el archivo Pruebas.t.t- '' endl, else 8hile)Farchivo.eof)** + archivo.!etline)linea, sizeof)linea**, cout '' linea '' endl, if))GGcontador H 5I*DD"* + cout '' -?=4J649;...-, cin.!et)*, 2 2 archivo.close)*, return ", 2
El pro!rama crea un objeto de la clase ifstream para abrir el archivo llamado Pruebas.t.t utilizando el constructor de clase y especificando la bandera ios33noreplace que evita que el archivo sea sobreescrito. 0i por al! n motivo ocurre un error al abrir el archivo se !enera el mensaje de error especificado en la l/nea #K. En ausencia de errores el pro!rama entra en un bucle 8hile el cual est evaluado por efecto de la funcin miembro eof) * de tal manera que el bucle se ejecuta hasta encontrar el final del archivo. 9tlizando la funcin miembro !etline) * se obtiene una l/nea de te.to y se e.hibe en pantalla, l/nea 5#, lue!o utilizamos una instruccin condicional if con el operador de mdulo )H* para determinar si se han le/do 5I l/neas de te.to. ?ada vez que el contador de l/neas dividido entre 5I d como resultado un res/duo de cero el pro!rama se detiene permitiendo leer las 5I l/neas de te.to previas. Para continuar se debe presionar la tecla enter y entonces el pro!rama leer y mostrar en pantalla las si!uientes 5I l/neas de te.to, l/neas 55 a la 5K.

Analizando el xito de E/S de archivos


En el pro!rama archiv"@.cpp se utiliz la funcin miembro fail) * para determinar el .ito de la operacin de apertura del archivo Pruebas.t.t. Ea funcin miembro fail) * produce el valor de # si ocurre un error en la operacin de archivo. 0imilarmente es recomendable utilizar otras funciones para verificar no solo la apertura de archivo sino tambin las operaciones de lectura y escritura, las funciones miembro que nos permiten stas pruebas son las si!uientes3 < !ood Produce un # si la operacin previa fu e.itosa. < eof Produce un # si se encuentra el final del archivo. < fail Produce un # si ocurre un error. < bad Produce un # si se realiza una operacin invlida. Jres de las cuatro funciones enlistadas quedan demostradas en el si!uiente pro!rama llamado archiv"I.cpp el cual copia el contenido del archivo llamado Pruebas.t.t en uno llamado ?opia.t.t. En primer lu!ar se crea un objeto de la clase ifstream llamado ori!en que nos sirve para abrir el archivo Pruebas.t.t para operaciones de lectura, la funcin miembro ori!en.fail) * nos indica la e.istencia de un error, en caso de que ste e.ista se desplie!a un mensaje en pantalla y el pro!rama termina. 0i la apertura del archivo Pruebas.t.t fu e.itosa se procede entonces a la si!uiente parte del pro!rama donde se crea un objeto de la clase ofstream llamado destino para operaciones de escritura el cual especifica que el archivo a crear se llamar ?opia.t.t y de acuerdo a la bandera ios33noreplace, si e.iste un documento con el nombre de ?opia.t.t la funcin constructora fallar, ste proceso es detectado por la funcin miembro destino.fail) * desple!ando un mensaje en pantalla y terminando el pro!rama. archiv"I.cpp es un pro!rama que sirve para copiar un archivo basado en caracteres ;0?66.

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // archiv"I.cpp // %emuestra .ito en operaciones de E/0 de archivos //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'fstream.h( &include 'stdlib.h( int main)* + ifstream ori!en)-Pruebas.t.t-*, char lineaA#5BC, if)ori!en.fail)** cerr '' -Error al abrir el archivo Pruebas.t.t- '' endl, else + ofstream destino)-?opia.t.t-, ios33noreplace*, if)destino.fail)** cerr '' -Error al crear el archivo3 ?opia.t.t- '' endl, else + 8hile)Fori!en.eof)** + ori!en.!etline)linea, sizeof)linea**, if)ori!en.!ood)** // si lectura oL y if)ori!en.eof)** // si eof, M( termina e.it)#*, // el pro!rama else destino '' linea '' endl, if)destino.fail)** + cerr '' -:allo de escritura en archivo- '' endl, e.it)#*, 2 2 2 destino.close)*, 2 ori!en.close)*, return ", 2
En caso que las operaciones de apertura de los archivos involucrados en el pro!rama archiv"I.cpp sean e.itosas, entonces se inicia un bucle en donde se lee en primer lu!ar una l/nea de te.to, l/nea 5N del pro!rama, el .ito de sta operacin es monitoreado por la funcin miembro ori!en.!ood) *, si sta funcin indica que la lectura del archivo fu e.itosa entonces la funcin miembro ori!en.eof) * verifica si la l/nea en cuestin es el final del archivo, si no es as/, entonces la l/nea le/da se escribe en el archivo ?opia.t.t, entonces le corresponde a la funcin miembro destino.fail) * verificar que el proceso de escritura tuvo .ito, l/nea @@ del pro!rama. El bucle se repite hasta encontrar el final del archivo, condicin que se verifica tanto en la linea 5O como en la 5P del pro!rama.

Operaciones con archivos inarios


Eas operaciones de flujos de archivos se ejecutan en forma predeterminada en modo de te.to, sin embar!o hay ocasiones en donde se requiere realizar operaciones en archivos binarios, como sucede con archivos de estructuras de datos aquellos que contienen datos numricos de punto flotante. ; manera de prueba trate de relaizar una copia de

un archivo ejecutable utilizando el pro!rama archiv"I.cpp, se dar cuenta que si bin, el pro!rama no marca errores, el resultado sencillamente no es el esperado. Ea prueba definitiva es comparar el tama>o en bytes del archivo ori!inal contra el tama>o del archivo copiado. El pro!rama archiv"O.cpp ejecuta operaciones de E/0 en archivos utilizando el modo binario )ios33binary*, ste pro!rama puede copiar efectivamente un archivo ejecutable, en el ejemplo ;rchiv"I.EQE, !enerando un nuevo archivo llamado ?opia.EQE, el nuevo cdi!o, basado en archiv"I.cpp es el si!uiente3

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // archiv"O.cpp // %emuestra operaciones con archivos binarios //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'fstream.h( &include 'stdlib.h( int main)* + ifstream ori!en)-;rchiv"I.e.e-, ios33binary*, char lineaA#C, if)ori!en.fail)** cerr '' -Error al abrir el archivo3 ;rchiv"I.e.e- '' endl, else + ofstream destino)-?opia.e.e-, ios33binary*, if)destino.fail)** cerr '' -Error al crear el archivo3 ?opia.e.e- '' endl, else + 8hile)Fori!en.eof)*RRFori!en.fail)** + ori!en.read)linea, sizeof)linea**, if)ori!en.!ood)** + destino.8rite)linea, sizeof)linea**, if)destino.fail)** + cerr '' -Error en el archivo3 ?opia.e.e- '' endl, e.it)#*, 2 2 else if)Fori!en.eof)** + cerr '' -Error en el archivo3 ;rchiv"I.e.e- '' endl, e.it)#*, 2 2 2 destino.close)*, 2 ori!en.close)*, return ", 2
=bservar que se utiliza la funcin miembro ori!en.read) * para leer un byte del archivo especificado por el objeto de la clase ifstream llamado ori!en, l/nea 5N. En forma similar, se utiliza la funcin miembro destino.8rite) * para escribir un byte en el archivo especificado para el objeto de la clase ofstream llamado ?opia.EQE, l/nea @" del pro!rama. Ea comprobacin de las operaciones de E/0 se realizan como se indic para el pro!rama archiv"I.cpp. 0i se desea utilizar los operadores de insercin y e.traccin para operaciones de E/0 en archivos binarios se requiere sobrecar!ar stos operadores, sto lo trataremos ms adelante cuando se aborde el tema de la sobrecar!a de operadores en ?GG.

!ectura " escritura en un archivo


Sasta este punto hemos efectuado operaciones, sea de escritura o bin de lectura en un archivo, tanto en formato de te.to como en formato binario pero todav/a no se han efectuado mbas operaciones en un mismo archivo. En ciertas aplicaciones es necesario efectuar operaciones de lectura/escritura en un archivo como es el caso de una base de datos, para esto es necesario crear un objeto de la clase fstream. ?uando un pro!rama abre un archivo para operaciones de E/0 ste mantiene el re!istro de dos apuntadores de archivo, uno para operaciones de lectura y otro para operaciones de escritura. ?omo en la mayor/a de los casos en que se abre un archivo para operaciones de E/0 se efect a acceso aleatorio, analizaremos sta condicin.

Acceso aleatorio de archivos


En los pro!ramas presentados hasta este punto se han realizados operaciones secuenciales en el archivo, ya sea para escritura lectura de datos, empezando por el principio y continuando hasta el final del mismo. Eas operaciones aleatorias en un archivo no necesariamente inician por el principio del archivo, en lu!ar de sto es posible desplazarse por el contenido del archivo para realizar una operacin de E/0. Para mover los apuntadores de archivo a posiciones

espec/ficas se utilizan dos funciones3 seeL!) * coloca el apuntador de escritura de archivo en un lu!ar espec/fico, y seeLp) * mueve el apuntador de lectura a una posicin espec/fica en el archivo, la sint.is de las funciones es sta3 seeLp)desplazamiento, posicion* seeL!)desplazamiento, posicion* El parmetro desplazamiento especifica la cantidad de bytes que se mover el apuntador de archivo, puede ser un valor positivo ne!ativo. El parmetro posicion especifica el lu!ar del archivo a partir del cual se mover el apuntador de archivo, de acuerdo a las si!uientes banderas < ios33be! %esde el principio del archivo < ios33cur %esde la posicin actual del apuntador < ios33end %esde el fin del archivo Para demostrar las operaciones aleatorias conviene !enerar un breve archivo de te.to en donde poder efectuar al!unas operaciones de E/0, use el si!uiente cdi!o3

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // letras.cpp // Tenera un abecedario //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'fstream.h( int main)* + ofstream archivo)-Eetras.t.t-*, for)char letraDU;U, letra 'DUVU, letraGG* archivo '' letra, archivo.close)*, return ", 2
El cdi!o !enera un alfabeto en el archivo llamado Eetras.t.t, ahora utilizaremos el pro!rama archiv"K.cpp para -nave!ar- por el contenido del archivo y !enerar una palabra ami!able en pantalla3

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // archiv"K.cpp // %emuestra lectura y escritura en un archivo //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'fstream.h( int main)* + char letra, fstream letras)-Eetras.t.t-, ios33in7ios33out*, letras.seeL!)N, ios33be!*, // obtiene la letra S letraDletras.!et)*, letras.seeLp)", ios33end*, letras '' letra, // coloca la letra al final letras.seeL!)M#@, ios33end*, // obtiene la letra = letra D letras.!et)*, letras.seeLp)", ios33end*, letras '' letra, letras.seeL!)M#N, ios33end*, // obtiene la letra E letra D letras.!et)*, letras.seeLp)", ios33end*, letras '' letra, letras.seeL!)", ios33be!*, // obtiene la letra ; letra D letras.!et)*, letras.seeLp)", ios33end*, letras '' letra, letras.seeL!)MI, ios33end*, 8hile)Fletras.eof)** cout.put))char*letras.!et)**, letras.close)*, return ", 2
=bserve que para posicionar el apuntador de lectura de archivo a partir del fin del mismo se utiliza un n mero ne!ativo y adems la lectura avanza hacia el final del archivo. Por la naturaleza del pro!rama archiv"K.cpp solo desple!ar el

mensaje S=E; en pantalla una sola vez, esto es porque las letras que forman la palabra -S=E;- se leen del archivo y a su vez se escriben al final del mismo, el cdi!o toma en cuenta las letras previamente escritas, lineas #P a la @5. Para un mejor entendimiento del funcionamiento del pro!rama utilice el depurador de errores de su compilador en la modalidad de paso por paso.

Salida a impresora
%e la misma manera en que es posible escribir la salida en un archivo, habr ocasiones en las que es necesario producir constancia en papel utilizando una impresora. En !eneral es posible tratar a la impresora como uno ms de los dispositivos disponibles para la salida de datos, se crea un objeto de la clase ofstream especificando como nombre de archivo la palabra PW4, tal y como lo demuestra el ltimo pro!rama de este tutorial, archiv"N.cpp3

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ // archiv"N.cpp // %emuestra la salida a impresora //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ &include 'fstream.h( &include 'stdlib.h( int main)* + char te.toA5OKC, ofstream impresora)-PW4-*, ifstream archivo)-Pruebas.t.t-*, if )archivo.fail)** cerr '' -Error al abrir el archivo3 Pruebas.t.t- '' endl, else + 8hile )Farchivo.eof)** + archivo.!etline)te.to, sizeof)te.to**, if )archivo.!ood)** + impresora '' te.to '' endl, if )impresora.fail)** + cerr '' -Error de escritura en impresora- '' endl, e.it)#*, 2 2 else if )Fimpresora.eof)** + cerr '' -Error al leer el archivo3 Pruebas.t.t- '' endl, e.it)#*, 2 2 archivo.close)*, impresora.close)*, 2 return ", 2