Fandom

Scratchpad

PLE:Unidad6

215,857pages on
this wiki
Add New Page
Discuss this page0 Share

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Entrada y Salida con ficheros

C++ nos proporciona un conjunto de clases que nos permiten la entrada y salida de datos desde y hacia ficheros. Concretamente disponemos de:

  • ofstream: Clase para la escritura de datos en ficheros
  • ifstream: Clase para la lectura de datos desde ficheros
  • fstream: Clase para la escritura/lectura de datos en ficheros.

ofstream

Esta clase no proporciona un flujo de datos (stream) para escribir datos en un fichero Para crearnos un objeto de tipo stream basta declararlo como ofstream, tal como se muestra a continuación:

#include <iostream>
#include <fstream>
using namespace std;

int main () 
{
	ofstream fs;
	fs.open ("fichero.txt");
	fs << "Escribiendo en un fichero mediante ofstream.\n";
	fs.close();
}

En este primer caso el stream no está conectado con un determinado fichero, por lo que deberemos conectarlo con posterioridad como veremos en la operación "open".

Por otro lado podemos declarar un stream de salida y conectarlo con un fichero determinada, tal como muestra el siguiente fragmento de código:

#include <iostream>
#include <fstream>
using namespace std;

int main () 
{
	ofstream fs("example.txt");
	fs << "Escribiendo en un fichero mediante ofstream.\n";
	fs.close();
}

ifstream

Esta clase no proporciona un flujo de datos (stream) para leer datos en un fichero Para crearnos un objeto de tipo stream basta declararlo como ifstream, tal como se muestra a continuación:

#include <iostream>
#include <fstream>
using namespace std;

int main () 
{
	ifstream fe;
	char cad[80]:
	fe.open ("fichero.txt");
	// Leemos una linea desde el fichero de estrada
	fe >> cad;
	// Escribimos en pantalla
	cout << cad;
	fe.close();
}

Abriendo ficheros

La operación de apertura nos permite conectar un fichero determinado con un objeto "stream". Una vez llevada a cabo la operación de apertura, todoas las operaciones de entrada o salida se llevarán a cabo sobre el fichero al cual hemos conectado el stream.

open(nombreFichero, modeApertura);

Al llevar a cabo la llamada a la función miembro "open()" debemos especificar el nombre del fichero y el modo de apertura a emplear. El modo de apertura es opcional y resulta la combinación de los valores mostrados en la siguiente tabla:

ios::inAbre en modo entrada.
ios::outAbre en modo salida.
ios::binaryAbre en modo binario.
ios::ateSe coloca al final del fichero.
ios::appAñade datos al final del fichero.
ios::truncTrunca el fichero.

Los valores expuestos se pueden combinar mediante el operados OR "|".

ofstream fs;
fs.open ("fichero.bin", ios::out | ios::app | ios::binary); 

Abre el fichero en modo binario, para escritura y añadiendo escribiendo los datos al fical del mismo.

El modo de apertura por defecto va a depender del tipo de stream que estemos empleando. En el caso de un stream de salida (ofstrem) se asume el modo "ios::out".

Para comprobar que un stream asociado a un fichero se ha abierto correctamente podemos utilizar la función miembro "is_open()" que nos devuelve un valor lógico que nos indica que la apertura se ha llevado a cabo correctamente.

#include <iostream>
#include <fstream>
using namespace std;

int main () 
{
	ofstream fs;
	fs.open ("example.txt");
	if(fs.is_open())
		fs << "Escribiendo en un fichero mediante ofstream.\n";
	else
		cout << "Error de apertura\n";
	fs.close();
}

Cerrando ficheros

Una vez que hemos finalizado todas las operaciones de entrada o salida en fichero, este debe ser liberado mediante la operación "close()".

fs.close();

Al llamar a esta función miembro, el objeto stream queda liberado y puede ser utilizado para acceder a otro fichero distinto. Además el fichero con el que estaba ligado el objeto stream puede ser abierto nuevamente por cualquier otro stream.

Estado de un stream

Disponemos de una serie de funciones miembro que nos permiten testar el estado de un stream. Todoas estas funciones devuelven valores de tipo lógico.

bad()Nos indica si en la última operación de escritura o lectura se ha producido un error debido a que el fichero no se encuentra abierto o no es posible anadirlos por falta de espacio.
fail()Nos indica error de escritura en los mismoa casos que el anterior pero ademas, en aquellos casos en los que el formato de datos no se corresponde con lo esperado, por ejemplo: leemos un caracter y esperabamos un

número.

eof()Devuelve un valor lógico que nos indica fin de fichero.
good()Nos indica que no se han producido ninguno de los anteriores errores.
#include <iostream>
#include <fstream>
using namespace std;

int main () 
{
	ifstream fe;
	char cad[80]:
	fe.open ("fichero.txt");
	// Leemos una linea desde el fichero de estrada
	fe >> cad;
	while(!fe.eof())
	{
		// Escribimos en pantalla
		cout << cad;
		// Leemos la siguiente linea
		fe >> cad;
	}
	fe.close();
}

Entrada y salida de datos mediante streams

Para la lectura y escritura de datos en fichero podemos utilizar varios operadores y funciones miembro que conocemos sobradamente por que ya han dsido empleadas con "cin" y "cout". No obstante vamos a recordarlas y mostraremos alguna nueva.

Operador de salida <<

El operador de salida se encuentra sobrecargado para los tipos elementales de datos y funciona de igual modo que con el objeto "cout"

Operador de entrada >>

El operador de entrada se encuentra sobrecargado para los tipos elementales de datos y funciona de igual modo que con el objeto "cin"

Lectura mediante get()

Permite la lectura de caracteres desde un stream de entrada. La función "get" se encuentra sobrecargado y contamos con las variantes mostradas a continución:

int get();				// Lee un caracter. Devuelve EOF si no hay disponible.
istream& get(char*, int len, char = '\n'); // Lee una cadena con la longitud especificada
istream& get(char&);			// Lee un caracter

Lectura con getline

Permite la lectura de una cadena de caracteres con un longitud especificada. Lee la cadena hasta que se encuentra el delimitador especificado, que por defecto es '\n'

istream& getline(char*, int, char = '\n');

ignore

Extrae del stream los siguientes "n" caracteres. Se detiene cuando encuentra el delimitador especificado.

istream& ignore(int n = 1, int delim = EOF);

peek

Nos devuelve el siquiente caracter del stream peron sin extraerlo.

int peek();

putback

Devuelve el caracter especificado al stream.

istream& putback(char);

Escritura con put

Escribe un carcater en un stream de salida.

ostream& put(char ch);

flush

Vacia el buffer del stream de salida, escribiendo todas las salidas pendientes.

ostream& flush();

Entrada y salida formateada

EL formato de la salida se puede cambiar mediante la manipulación de flags. Podemos emplear funciones específicas como: falgs, setf y unsetf. La manipulación de los flags tiene un efecto permanente y afecta a todas las entradas y salidas sucesivas.

Otro método para cambiar el formato de la entrada y salida es mediante el uso de unas funciones especiales denominadas manipuladores. Estas no tiene efecto permanente sobre el stream en cuestión. Para utilizar manipuladores debemos incluir el fichero de cabecera <iomanip>

Manipulador setw

Cambia la anchura de la salida indicando el número de caracteres a emplear.

#include <iostream>
#include <iomanip>
using namespace std;
 
int main () 
{
	int num = 23;
	ofstream fs("ejemplo.txt");
	if(fs.good())
	{
		fs << "#" << setw(6) << num << "#" << endl;
		fs.close();
	}
}

Manipulador setbase

Cambia la base de numeración empleada en la salida. Admite como parámetro los valores 8, 10 y 16.

#include <iostream>
#include <iomanip>
using namespace std;
 
int main () 
{
	int num = 23;
	ofstream fs("ejemplo.txt");
	if(fs.good())
	{
		fs << "base  8 =" << setbase(8) << num;
		fs << "base 10 =" << setbase(10) << num; 
		fs << "base 16 =" << setbase(16) << num <<endl;
		fs.close();
	}
}

Manipulador setfill

Especifica el caracter de relleno utilizado en la salida. Este caracter de relleno se empleará en el caso de que la anchura requerida sea mayor que la necesaria.

#include <iostream>
#include <iomanip>
using namespace std;
 
int main () 
{
	int num = 23;
	ofstream fs("ejemplo.txt");
	if(fs.good())
	{
		fs << setfill('0') << num << endl;
		fs.close();
	}
}

Manipulador setprecision

Podemos indicar el número de dígitos a utilizar en la salida para mostrar números reales.

#include <iostream>
#include <iomanip>
using namespace std;
 
int main () 
{
	float pi = 3.14159;
	ofstream fs("ejemplo.txt");
	if(fs.good())
	{
		fs << setprecision(3) << pi << endl;
		fs.close();
	}
}

Manipuladores setiosflags y resetiosflags

Estas funciones permiten activar los flgas de formato de datos. Podemos especificar los siguientes:

flagAcción
skipwssalta espacios en operaciones de lectura
leftalinea a la izquierda
rightalinea a la derecha
internalcaracter de relleno antes del punto decimal
decdecimal
octoctal
hexhexadecimal
showbasemuestra la base utilizada
showpointmuestra el punto decimal
uppercasemayúsculas
showposmuestra el signo '+'
scientificnotación científica
fixedpunto decimal en numeros flotantes
unitbufvacía el buffer tras cada operación de salida

Manipulador dec

Emplea formato decimal para la lectura o escritura de números.

Manipulador hex

Emplea formato hexadecimal para la lectura o escritura de números.

Manipulador oct

Emplea formato octal para la lectura o escritura de números.

Función fill

Especifica el caracter de relleno a utilizar en la salida

  int num = 23;
  fs.width(10);
  fs.fill('%');
  fs << "|" << num << "|" << endl;

Función precision

Cambia el numero de dígitos a mostrar en números reales.

Función setf

Permite activar/desactivar los flags de formato.

long setf(long);			

Ejemplo:

int num = 17;
fs.setf(ios::left);
fs << num;

Función unsetf

Permite desactivar los flags de formato.

void unsetf(long mascara);

Desactiva los flags que estén activos en el parámetro.

int num = 17;
fs.unsetf(ios::left | ios::right | ios::internal);
fs.setf(ios::left);
fs.width(10);
fs << num;

Función flags

Permite cambiar o leer los flags de manipulación de formato:

long flags() const;  		// Devuelve el valor actual de los flags.
long flags(long valor);

Ejemplo

int num = 18;
long f;
f = flags();
f |= ios::left;
fs.flags(f);
fs.width(10);
fs << num;

Lectura y escritura en ficheros binarios

Para la lectura o escritura sobre streams en formato binario empleamos las funciones read y write mostradas a continucación.

write

Permite la escritura de datos de un stream. Debemos pasarle un puntero a un caracter y especificarle el número de bytes a escribir.

ostream& write(const char*, int n);

Se puede utilizar para la escritura de cualquier tipo de datos, basta hacer la conversión a "char *".

#include <iostream>
#include <fstream>
using namespace std;

struct contacto
{
      char nombre[50];
      char telefono[15];
      int edad;
};

int main ()
{
	contacto c;
	ofstream fs("agenda.txt", ios::out | ios::binary);

        strcpy(c.nombre, "pepe");
        strcpy(c.telefono, "1122");
        c.edad = 20;


	if(fs.good())
	{
		fs.write ((char *) &c, sizeof(contacto));
		fs.close();
	}
}

Lectura de datos con read

Permite la lectura de datos de un stream, Debemos pasarle un puntero a un caracter y especificarle el número de bytes a leer. Esta función almacenará los datos en la posición especificada por el puntero.

istream& read(char*, int);

Se puede utilizar para la lectura de cualquier tipo de datos, basta hacer la conversión a "char *", tal como muestra el siguiente código:

#include <iostream>
#include <fstream>
using namespace std;

struct contacto
{
      char nombre[50];
      char telefono[15];
      int edad;
};

int main ()
{
	contacto c;
	ifstream fe("agenda.txt", ios::in | ios::binary);

	if(fe.good())
	{
		fe.read ((char *) &c, sizeof(contacto));
                cout << "Nombre = " << c.nombre << endl;
                cout << "Telf = " << c.telefono << endl;
                cout << "Edad = " << c.edad;

		fe.close();
	}
        cin.ignore();
        cin.get();
}

Ficheros de acceso aleatorio

Hasta ahora la lectura y escritura en ficheros la hemos llevado a cabo de forma secuencial. Sin embargo es posible desplazarnos a través de un strem para poder llevar a cabo las operaciones de lectura o escritura a partir de la posición que deseemos.

tellg() and tellp()

Estas dos funciones miembro nos devuelven un dato de tipo entero indicando la posición en la que nos encontramos dentro de un fichero, por lo que la siguiente operación de entrada o salida será llevada a cabo en dicho punto.

pos_type tellg();
pos_type tellp();

seekg() and seekp()

Estas funciones sirven para desplazarnos a traves de un stream. Existen dos variantes, la primera "seekg", se utiliza para la lectura (get) y la segunda para la escritura (put). Dsiponemos de una primera variante de ambas funciones que reciben como parámetro el valor de la posición:

istream_type& seekg( posicion );
ostream_type& seekp( posicion );

En este caso el desplazamiento se tomará a partir del principio del fichero, por lo que dicho valor coincidirá con el devuelto por la función "tellg" y "tellp". Existe otra versión de ambas funciones:

istream_type& seekg( desplazamiento, direccion );
ostream_type& seekp( desplazamiento, direccion );

En este caso las funciones reciben un segundo parámetro de tipo enumerado que sirve para indicar el punto de partida a partir del cual vamos a tomar en consideración el desplazamiento.

ios::begesplazamiento a partir del comienzo del stream
ios::curDesplazamiento a partir de la posición actual del stream
ios::endDesplazamiento a partir del final del stream

Ejemplo:

#include <iostream>
#include <fstream>
using namespace std;

int main() 
{
	long inicio,fin;
	ifstream fe("ejemplo.txt");
	inicio = fe.tellg();
	fe.seekg (0, ios::end);
	fin = fe.tellg();
	fe.close();
	cout << "tamaño del fichero = " << (fin - inicio) << " bytes.\n";
}

gcount()

Esta función nos indica en numero de bytes leidos en la última operación de lectura no formateada. Esta función se puede utilizar junto con la función read para determinar el número de bytes leidos.

Algunos ejemplos de acceso a ficheros binarios

A continuación mostramos una serie de ejemplo de escritura y lectura sobre ficheros binarios, accediendo de forma secuencial y directa (mediante seekg() y seekp()).

Ejemplo 1- Escribe datos de un conjunto de alumnos en un fichero binario.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib>
using namespace std;

struct alumno
{
        char nombre[20];
        int nota;
};

int main()
{
        ofstream fs;
	alumno a;
	char nombre[80], c='s';

	cout << "Nombre del fichero: ";
	cin >> nombre;
	fs.open(nombre, ios::out | ios::binary);
	if(!fs.good())
        {
		cout << "Error";
                exit(1);
        }
	else
	{
		while(c != 'n')
                {
                        system("cls");
                        cout << "Introduzca un nombre ";
                        cin.getline(a.nombre,20);
                        cout << "Introduzca una nota ";
                        cin >> a.nota;
                        fs.write((char *) &a, sizeof(alumno));
                        cout << "Continuar(s/n) ";
                        cin >> c;
                }
		fs.close();
	}
}

Ejemplo 2- Lee los datos almacenados en el fichero anterior accediendo secuencialmente y los muestra en pantalla.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib>
using namespace std;

struct alumno
{
        char nombre[20];
        int nota;
};

int main()
{
        ifstream fe;
	alumno a;
	char nombre[80];

	cout << "Nombre del fichero: ";
	cin >> nombre;
	fe.open(nombre, ios::in | ios::binary);
	if(!fe.good())
        {
		cout << "Error";
                exit(1);
        }
	else
	{
                fe.read((char *) &a, sizeof(alumno));
		while(!fe.eof())
                {
                        cout << "Nombre " << a.nombre << endl;
                        cout << "Nota " << a.nota << endl;
                        fe.read((char *) &a, sizeof(alumno));
                }
		fe.close();
	}
        cin.ignore();
        cin.get();
}

Ejemplo 3- Lee datos de alumnos en un fichero binario mediante acceso directo.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib>
using namespace std;

struct alumno
{
        char nombre[20];
        int nota;
};

int main()
{
        ifstream fe;
	alumno a;
        long pos;
	char nombre[80];

	cout << "Nombre del fichero: ";
	cin >> nombre;
	fe.open(nombre, ios::in | ios::binary);
	if(!fe.good())
        {
		cout << "Error";
                exit(1);
        }
	else
	{
                cout << "Introduzca la posición (-1 para finalizar): ";
                cin >> pos;
                fe.seekg(pos * sizeof(alumno),ios::beg);
                fe.read((char *) &a, sizeof(alumno));
		while(pos != -1)
                {
                        cout << "Nombre " << a.nombre << endl;
                        cout << "Nota " << a.nota << endl;
                        cout << "Introduzca la posición (-1 para finalizar): ";
                        cin >> pos;
                        fe.seekg(pos * sizeof(alumno),ios::beg);
                        fe.read((char *) &a, sizeof(alumno));
                }
		fe.close();
	}
        cin.ignore();
        cin.get();
}

Ejemplo 4- Lee y escribe sobre un fichero binario mediante acceso directo.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <stdlib>
using namespace std;

struct alumno
{
        char nombre[20];
        int nota;
};

int main()
{
        fstream f;
	alumno a;
        long pos;
	char nombre[80];

	cout << "Nombre del fichero: ";
	cin >> nombre;
	f.open(nombre, ios::in | ios::out | ios::binary);
	if(!f.good())
        {
		cout << "Error";
                exit(1);
        }
	else
	{
                cout << "Introduzca la posición (-1 para finalizar): ";
                cin >> pos;
                f.seekg(pos * sizeof(alumno),ios::beg);
                f.read((char *) &a, sizeof(alumno));
		while(pos != -1)
                {
                        // Mostramos
                        cout << "Nombre " << a.nombre << endl;
                        cout << "Nota " << a.nota << endl;
                        // Modificamos
                        cout << "Introduzca nombre nuevo ";
                        cin >> a.nombre;
                        cout << "Introduzca nota nueva ";
                        cin >> a.nota;
                        f.seekp(pos * sizeof(alumno),ios::beg);
                        f.write((char *) &a, sizeof(alumno));

                        cout << "Introduzca la posición (-1 para finalizar): ";
                        cin >> pos;
                        f.seekg(pos * sizeof(alumno),ios::beg);
                        f.read((char *) &a, sizeof(alumno));
                }
		f.close();
	}
        cin.ignore();
        cin.get();
}

Ejercicios

  1. Escribir varias lineas de texto en un fichero. Solución.
  2. Leer un fichero de texto y mostrarlo en pantalla. Solución.
  3. Cifrar un fichero de texto mediante el método Cesar. Solución.
  4. Descifrar un fichero de texto mediante el método Cesar. Solución.
  5. Contar la frecuencia de aparición de caracteres en un fichero de texto. Solución.
  6. Contar la frecuencia de aparición de palabras en un fichero de texto.Solución.
  7. Agregar a la agenda electrócia la opción de lectura y escritura en fichero. Solución.
  8. Disponemos de un fichero de texto (nombre, nota y curso) con las notas de los alumnos pertenecientes a los grupos de ASI y DAI. Crea un programa que lea dicho fichero y almacene en dos ficheros los alumnos correspondientes a cada grupo mencionado. Solución.
  9. En un fichero tenemos almacenados el nombre y apellidos y nota de una clase.Crea un programa que cree lea dicho fichero y almacene los aprobados y suspensos en ficheros seperados.
  10. Lee dos ficheros conteniendo una secuencia de numeros ordenados y escribelos en un único fichero manteniendo el orde de la secuencia. Solución
  11. Lee un fichero de texto conteniendo una lista de alumnos y notas y almacenalos en un fichero html usando una tabla.
  12. Lee un fichero y altera el orden de las letras excepto la primera y última letra de cada palabra tal como aparece en el siguiente texto: "Segun un estudio de una universidad inglesa, no importa el orden en el que las letras estan escritas, la unica cosa importante es que la primera y la ultima letra esten escritas en la posicion correcta. El resto pueden estar totalmente mal y aun podras leerlo sin problemas. Esto es porque no leemos cada letra por si misma sino la palabra como un todo. Personalmente me parece increible...". El resultado debe asemejarse al siguiente: "Seugn un etsduio de una uivenrsdiad ignlsea, no ipmotra el odren en el que las ltears etsan ersciats, la uicna csoa ipormtnate es que la pmrirea y la utlima ltera esten ecsritas en la psiocion cocrrtea. El rsteo peuden estar ttaolmntee mal y aun pordas lerelo sin pobrleams. Etso es pquore no lemeos cada ltera por si msima snio la paalbra cmoo un tdoo. Pesornamelnte me preace icrneilbe..."
  13. Lee un fichero de texto y numera las lineas.
  14. Lee un fichero y cuenta el numero de lineas, espacias, palabras y numeros que contiene.
  15. Crea un programa que lea un fichero de texto y lo almacene en formato html. Tomamos la primera linea del fichero de texto como título del fichero html. El programa contemplará el uso de parámetros de llamada en la función main. Solución.
  16. Mini editor de texto. Debe permitir insertar, borrar y modificar lineas de un texto. Tembien contará con opciones para leer y escribir el texto editado sobre un archivo. Solución.
  17. Crea programa que permita gestionar un diccionario inglés-español.
  18. Crea un programa que permita trabajar con un fichero de articulos. El fichero debe incluir para cada artículo un codigo, una descripcion, precio y cantidad disponible en almacen. El programa permitirá el registro de nuevos artículos, la modificación de los existentes y la consulta de forma aleatoria y secuencial.
  19. Crear un programa que permita generar una sopa de letras con las palabras cargadas desde un fichero de texto. El resultado se almacenará en un fichero de texto.
  20. Editor hexadecimal. Solución.
  21. Lee cabecera de un fichero "BMP". Solución.
  22. Transforma una imagen BMP de color a BN.Solución.
  23. Esteganografía - Incluir texto al final de un BMP Solución.
  24. Esteganofrafía - Incluir texto dentro de los datos de un BMP Solución.
  25. Editar etiquetas ID3 (www_mp3tag_de)
  26. Uso de una libreria de compresión de datos

Also on Fandom

Random wikia