You are on page 1of 10

ESCUELA DE INGENIERA DE SISTEMAS

DEPARTAMENTO DE COMPUTACIN
PROGRAMACIN 2
PRCTICA DE LABORATORIO 12

Archivos, Archivos de texto


Contenido
Introduccin .................................................................................................... 1
Archivos y flujos en C++ ................................................................................. 1
Archivos de encabezado................................................................................. 2
Abrir Archivos.................................................................................................. 2
Modos de apertura de archivo ........................................................................ 4
Cerrar archivos ............................................................................................... 5
Lectura y Escritura de un Archivo de texto...................................................... 5
Estado de las operaciones de E/S sobre archivos.......................................... 9
Ejercicio .......................................................................................................... 9

Introduccin
Un archivo es un grupo de registros relacionados almacenados en
memoria secundaria. Por ejemplo, un archivo de nmina de una
compaa contiene normalmente un registro por cada empleado. De
esta manera, el archivo de nmina de una compaa pequea podra
contener slo 20 registros y, en cambio un archivo de nmina de
una compaa grande podra contener hasta 50.000 registros.
La ventaja es que la informacin almacenada en un archivo es
persistente en el tiempo, no es susceptible a fallas elctricas y
puede reproducirse y transportarse a bajo costo.

Archivos y flujos en C++


C++ ve a cada archivo simplemente como una secuencia de bytes que
termina con un marcador especial de fin de archivo. Las
bibliotecas estndar de C++ proporcionan un amplio conjunto de
capacidades de entrada/salida.
En general, la E/S en C++ se da en flujo de bytes. Un flujo es
simplemente una secuencia de bytes. En las operaciones de entrada,
los bytes fluyen desde un dispositivo (por ejemplo: teclado,
unidad de disco, etc.) hacia la memoria principal. En operaciones
de salida los bytes fluyen de la memoria principal hacia un
dispositivo (por ejemplo: pantalla, impresora, unidad de disco,
etc.). Ya se ha visto que existen cuatro objetos que se crean
automticamente cuando se utiliza la biblioteca iostream: cin,
cout, cerr y clog. Estos objetos asocian canales de comunicacin
entre un programa y un archivo o dispositivo particular. Por
ejemplo, el objeto cin (flujo de entrada estndar) permite que un
programa reciba datos desde el teclado; el objeto cout (flujo de
salida estndar) permite que un programa enve datos a la

pantalla, y los objetos cerr y clog (flujo de error estndar)


permiten que un programa enve mensajes de error a la pantalla.

Archivos de encabezado
Para realizar el procesamiento de archivos en C++ se deben incluir
los archivos de encabezado <iostream.h> y <fstream.h>. El archivo
<fstream.h> incluye las definiciones para las clases ifstream
(para entrada desde un archivo), ofstream (para salida hacia un
archivo) y fstream (para entrada y salida de un archivo).
ios
istream
ifstream

ostream
iostream

ofstream

fstream

Para crear un flujo para leer/escribir archivos a disco (archivos


fsicos), lo primero que debe hacer es definir un objeto (llamado
tambin archivo lgico) para una de las clases de archivo
convenientemente:
la clase ifstream, para definir los archivos que se usan
exclusivamente para entrada de datos (leer).
la clase ofstream, para definir los archivos que se usan
exclusivamente para la salida de datos (escribir).
la clase fstream, para definir archivos de entrada y/o salida
de datos.
El siguiente programa muestra la forma de crear estos objetos de
la clase fstream:
#include <fstream>
using namespace std;
int main(){
ifstream lectura; // para leer un archivo
ofstream escritura; // para escribir un archivo
fstream lecturaEscritura; // para leer y escribir un archivo
return 0;
}

Abrir Archivos
El mtodo open(), heredado por todas las clases del flujo de
archivos, permite asociar el objeto del flujo de archivos (archivo
lgico) a un archivo fsico en disco y luego abrirlo para su
acceso. La forma de llamar a este mtodo es:
<objeto de flujo de archivo>.open (<nombre del archivo fsico>,
<modo de apertura de archivo>);

El nombre del objeto es seguido por un punto y despus por la


funcin open() y luego sus argumentos. Los argumentos son: un
nombre del archivo en disco y un designador del modo de apertura
(opcional). El nombre del archivo en disco se debe ajustar a los
requerimientos del sistema operativo. El nombre del archivo en el
disco fsico se puede especificar directamente dentro de dobles
comillas (por ejemplo ejemplo.txt) o en forma indirecta como una
variable tipo cadena. El argumento indicador del modo de apertura
define que tipo de acceso se realizar dentro del archivo
(detallado en la siguiente seccin).
Nota: El (los) modo(s) de lectura/escritura siempre debe(n)
especificarse cuando un objeto de flujo de archivos se define con
la clase fstream, pues por definicin, esta clase se usa para
ambos accesos a archivos de entrada y salida (lectura/escritura)
Los modos lectura/escritura no necesitan especificarse cuando se
abren archivos definidos por las clases ifstream u ofstream,
porque los archivos son predeterminados como entrada y salida
respectivamente.
Compile y ejecute el siguiente programa y luego verifique los
archivos creados en el directorio. Por qu solo se crea el
archivo ejemplo2.txt?
#include <fstream>
using namespace std;
int main(){
ifstream lectura; // para leer un archivo fsico
ofstream escritura; // para escribir un archivo fsico
fstream lecturaEscritura; // para leer y escribir un archivo
// Archivo logico lectura que lea del archivo de disco ejemplo1.txt.

lectura.open("ejemplo1.txt");
// Archivo lgico escritura que escribe al archivo de disco ejemplo2.txt.

escritura.open("ejemplo2.txt");
// Archivo logico lescturaEscritura que lea y escriba el archivo ejemplo3.txt.

lecturaEscritura.open("ejemplo3.txt", ios::in | ios::out);


return 0;
}
Despus de crear los objetos y abrirlos, se recomienda verificar
si la operacin tuvo xito a travs del operador sobrecargado ! de
ios, retornando true si la operacin falla. Algunos posibles
errores son: intentar abrir un archivo que no existe en modo
lectura, abrir un archivo de lectura sin permiso y abrir un
archivo para escritura si no hay espacio en disco.
El siguiente cdigo realiza esta verificacin (compile y ejecute):
#include <iostream>
#include <fstream>
using namespace std;
int main(){

ifstream lectura; // para leer un archivo


ofstream escritura; // para escribir un archivo
fstream lecturaEscritura; // para leer y escribir un archivo
lectura.open("ejemplo1.txt");
escritura.open("ejemplo2.txt");
lecturaEscritura.open("ejemplo3.txt", ios::in | ios::out);
if (!lectura) cout << "No se puede abrir el acrhivo lectura -> ejemplo1.txt" << endl;
if (!escritura) cout << "No se puede abrir el acrhivo
escritura --< ejemplo2.txt" << endl;
if (!lecturaEscritura) cout << "No se puede abrir el acrhivo
lecturaEscritura --> ejemplo3.txt" << endl;
return 0;
}
Los constructores paramtricos de las clases fstream, ifstream y
ofstream
adems
de
crear
el
objeto
del
archivo
fsico
correspondiente, permiten abrir un archivo al igual que el mtodo
open(). El siguiente cdigo lo muestra (compile y ejecute):
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ifstream lectura("ejemplo1.txt");
ofstream escritura("ejemplo2.txt");
fstream lecturaEscritura("ejemplo3.txt", ios::in | ios::out);
if (!lectura) cout << "No se puede abrir el acrhivo lectura -> ejemplo1.txt" << endl;
if (!escritura) cout << "No se puede abrir el acrhivo
escritura --< ejemplo2.txt" << endl;
if (!lecturaEscritura) cout << "No se puede abrir el acrhivo
lecturaEscritura --> ejemplo3.txt" << endl;
return 0;
}

Modos de apertura de archivo


Dependiendo del propsito del programa debe indicar el modo de
acceso, por ejemplo es posible que sea necesario agregar datos a
los ya existentes en el archivo, o quiz que las operaciones del
programa no se lleven a cabo en caso de que el archivo
especificado exista en el disco, etc., Dependiendo del caso
podemos especificar el modo de apertura segn la siguiente tabla:
Modo
ios::app

Descripcin
Anexa toda la salida al final del archivo

ios::ate

ios::in
ios::out
ios::nocreate
ios::noreplace
ios::trunc
ios::binary

Abre en modo salida y se coloca el apuntador del


archivo al final del mismo. Los datos pueden
escribirse en cualquier parte del archivo
Operaciones de lectura. Esta es la opcin por
defecto para objetos de la clase ifstream.
Operaciones de escritura. Esta es la opcin por
defecto para objetos de la clase ofstream.
Si el archivo no existe se suspende la operacin
Crea un archivo, si existe uno con el mismo
nombre la operacin se suspende.
Crea un archivo, si existe uno con el mismo
nombre lo borra.
Operaciones binarias (no es texto)

Cerrar archivos
Despus de terminar el procesamiento del archivo, deber cerrar el
archivo para garantizar su contenido y permitir su posterior uso.
Esto se realiza con la funcin close() Para cerrar un archivo, lo
que necesita hacer es llamar al mtodo close() con un objeto de
flujo
de
archivo.
Como
resultado,
los
enunciados
lecturaEscritura.close(),
escritura.close()
y
lectura.close()
debern cerrar los archivos que se abrieron anteriormente.

Lectura y Escritura de un Archivo de texto


Se escribe un archivo en disco usando su objeto de flujo de
archivo de salida y el operador de insercin <<, de la misma forma
como se us el objeto de flujo de archivo estndar cout y el
operador <<. De esta manera, luego de abrir un objeto de archivo
de salida las siguientes instrucciones permiten escribir:
ofstream salida;
salida.open(ejemplo.txt);
salida << Esto es un ejemplo << endl;
salida.close();
Verifique en su disco que aparece el archivo ejemplo.txt y que
contiene el texto. Se pruebe escribir cualquier tipo de variable
(string, arreglo de caracteres, entero, etc.) que tenga definido
el operador <<. El siguiente programa genera un archivo de texto
donde cada lnea contiene un nmero de lnea correspondiente al
valor inicial del nmero de lneas solicitado al usuario (copie,
compile, ejecute y verifique el archivo creado con su contenido):
#include <iostream>
#include <fstream>
using namespace std;
int main(){
int numl,i;
ofstream salida; // flujo de salida
// Apertura del archivo, crear y abrir un nuevo archivo

salida.open("ejemplo-escribir.txt");
// Verificando la operacion -- si el archivo existe o no
if (!salida)
{
cout<<"No se puede abrir el archivo\n";
exit(1);
}
else
{
cout<<"Suministre el total de lineas del archivo: ";
cin>>numl;
for (i=0;i<numl;i++)
{
//Escritura de un archivo de texto
salida << i+1 <<"\n";
}
}
salida.close(); //Cierre del archivo
cout<<"****** Archivo Procesado ******\n";
return 0;
}
Se lee un archivo en disco con el objeto de flujo de archivo de
entrada y el operador de extraccin >>, tal como se usa el objeto
de flujo de archivo estndar cin y el operador >>. De esta manera,
luego de abrir un objeto de archivo de entrada las siguientes
instrucciones permiten leer la primera secuencia de caracteres
delimitada por el carcter espacio en blanco:
string cadena;
ifstream entrada;
entrada.open(ejemplo.txt);
entrada >> cadena;
cout << cadena << endl; // muestra lo ledo del archivo
entrada.close();
Ejecute el cdigo anterior y verifique lo que muestra por
pantalla, note que no es toda la lnea que contiene el archivo
ejemplo.tx. Note que la cadena se defini como un string por tanto
debe incluir la clase string de C++. Si desea obtener toda una
lnea del archivo de entrada (independientemente del nmero de
palabras) debe usarse la funcin getline, en lugar de entrada >>
cadena, de la siguiente forma:
getline(entrada, cadena, \n);
Copie, compile y ejecute el siguiente cdigo que muestra como leer
el archivo ejemplo-escribir.txt lnea a lnea y mostrarlo por
pantalla.
#include <iostream>
#include <fstream>

#include <string>
using namespace std;
int main(){
string i;
ifstream entrada; // flujo de entrada
// Apertura del archivo: abrir un nuevo existente)
entrada.open("ejemplo-escribir.txt");
// Verificando la operacion -- si el archivo existe o no
if (!entrada)
{
cout<<"No se puede abrir el archivo\n";
exit(1);
}
else
{
/*
do
{
//Lectura de un archivo de texto
entrada >> i;
cout << i << endl; // muestra lo pantalla
} while (entrada);
*/
}
entrada.close();
//Cierre del archivo
cout<<"****** Archivo Procesado ******\n";
return 0;
}
Hay muchas formas de hacer un ciclo iterativo para leer un archivo
de forma secuencial lnea por lnea hasta el final. Las siguientes
son alternativas:
while (entrada >> i) {
cout << i << endl; // muestra lo pantalla
}
while (!entrada.eof()) {
entrada >> i;
cout << i << endl; // muestra lo pantalla
}
entrada >> i;
while (!entrada.eof()) {
cout << i << endl; // muestra lo pantalla
entrada >> i;
}
Sin embargo, la ltima alternativa deja de procesar la ltima
lnea. Esto se debe a que cuando se abre un archivo de lectura, un
cursor que forma parte del archivo lgico se ubica en la primera
lnea del archivo fsico, luego una vez leda la lnea el cursor
se ubica en la siguiente. Cuando se ejecuta eof(), este mtodo

determina si dicho cursor esta parado en el carcter de fin de


archivo y se da el valor de verdad en caso positivo, entonces se
sale del ciclo y no se procesa la ltima lnea. Se debe tener
cuidado con la forma en que realiza el ciclo iterativo.
Cuando se tienen archivos de textos estructurados, es decir con
ms de un valor por lnea y de tamao fijo el nmero de campos. Se
puede escribir con el operador << y agregar el separador que se
necesite. Para leer de debe usar el operador >> tantas veces como
valores estn separados por un espacio en blanco o fin de lnea.
El siguiente cdigo ilustra como crear y leer un archivo de 2
enteros por lneas:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
int numl,i,j;
ofstream salida; // flujo de salida
salida.open("ejemplo-escribir2.txt",ios::out);
if (!salida)
{
cout<<"No se puede abrir el archivo\n";
exit(1);
}
else
{
cout<<"Suministre el total de lineas del archivo: ";
cin>>numl;
for (i=0;i<numl;i++)
{
//Escritura de un archivo de texto
salida << i+1 << " " << numl+i <<"\n";
}
}
salida.close(); //Cierre del archivo
cout<<"****** Archivo de salida Procesado ******\n";
ifstream entrada; // flujo de entrada
entrada.open("ejemplo-escribir2.txt");
if (!entrada)
{
cout<<"No se puede abrir el archivo\n";
exit(1);
}
else
{
do
{
//Lectura de un archivo de texto
entrada >> i >> j;
cout << i << " " << j << endl; // muestra lo pantalla
} while (entrada);
}
entrada.close();
//Cierre del archivo
cout<<"****** Archivo de entrada Procesado ******\n";

return 0;
}
El archivo ejemplo-escribir2.txt para un valor numl = 3 es el
siguiente:
1 3
2 4
3 5
De la misma forma puede escribirse y leer un registro (struct de
C++) sobre un archivo de texto, de la siguiente forma:
struct datos{
int ci;
string nombre;
};
. . .
ofstream salida(ejemplo3.txt);
datos D;
salida << D.ci << "\t" << D.nombre <<"\n";
salida.close();
. . .
ifstream entrada("ejemplo-escribir3.txt");
datos D1;
entrada >> D1.ci >> D1.nombre;
entrada.close();
Si el campo nombre puede esta formado por ms de una palabra
entonces debe usarse getline para leer toda la lnea y procesarla
con los mtodos de la clase string, pues el operador >> y << no
servirn en este caso.

Estado de las operaciones de E/S sobre archivos


Se recomienda utilizar los siguientes mtodos para verificar el
xito de las operaciones de, apertura, lectura y escritura sobre
archivos:
good(): produce un 1 si la operacin previa fu exitosa.
eof(): produce un 1 si se encuentra el final del archivo.
fail(): produce un 1 si ocurre un error.
bad(): produce un 1 si se realiza una operacin invlida.

Ejercicio
1. El departamento de Robtica de una compaa tiene varios
tipos de robots. Para cada robot se tiene un archivo de texto
secuencial (Archivo 1) que contiene los registros de las
rdenes vlidas formadas por 2 campos:

a. el campo parte (cabeza, manos, brazos, piernas, pies,


etc.) del robot y
b. el campo movimiento (derecha, izquierda, arriba, abajo,
etc.) de la parte
Este archivo contiene registros ordenados por el campo parte
(puede estar duplicado!). Por otra parte, la interfaz del
robot puede ingresar todas las combinaciones de partes y
movimientos a travs del Archivo 2, pero para cada tipo de
robot el Archivo 1 determina sus movimientos vlidos. El
Archivo 2, entonces expresa los requerimientos del usuario
para intentar mover el robot y contiene la misma estructura
que el Archivo 1 con la diferencia que contiene movimientos
vlidos e invlidos desordenados del robot. Se quiere que
ud., procese los archivos de texto secuencial para que:
a) Implemente un validador: dado como parmetros el Archivo 1
y Archivo 2, diga si el Archivo 2 es vlido o invlido
segn el Archivo 1
b) Implemente un filtro: dado como parmetros el Archivo 1 y
Archivo 2, genere la particin del Archivo 2 en dos
archivos de salidas: Ordenes Vlidas y Ordenes Invlidas,
segn el Archivo 1
Por ejemplo:
Archivo 2
PIED
DER
CABEZA ARR
CABEZA DER
BRAZOD DER
MANOI
ARR
PIEI
IZQ
BRAZOI
IZQ

Archivo 1
BRAZOD ABA
BRAZOD ARR
CABEZA ARR
CABEZA DER
CABEZA IZQ
MANOD
IZQ

Archivo1
Archivo2

Archivo 1
Archivo 2

Validador
(a)

Filtro (b)

Invlido

Ordenes Invlidas
PIED
DER
BRAZOD
DER
MANOI
ARR
PIEI
IZQ
BRAZOI
IZQ
Ordenes Vlidas
CABEZA
ARR
CABEZA
DER

Elaborado: prof. Hilda Contreras


Revisado: prof. Rafael Rivas y prof. Gilberto Daz.

You might also like