Está en la página 1de 10

Programación Estructurada

Archivos en C++

Muy a menudo necesitamos almacenar cierta cantidad de datos de forma


más o menos permanente. La memoria del ordenador es volátil, y lo que es peor,
escasa y cara. De modo que cuando tenemos que guardar nuestros datos
durante cierto tiempo tenemos que recurrir a sistemas de almacenamiento más
económicos, aunque sea a costa de que sean más lentos.
Durante la historia de los ordenadores se han usado varios métodos
distintos para el almacenamiento de datos. Al principio se recurrió a cintas de
papel perforadas, después a tarjetas perforadas. A continuación se pasó al
soporte magnético, empezando por grandes rollos de cintas abiertas.
Hasta aquí, todos los sistemas de almacenamiento externo eran
secuenciales, es decir, no permitían acceder al punto exacto donde se guardaba
la información sin antes haber partido del principio y sin haber leído toda la
información desde el principio hasta el punto donde se encontraba la que
estábamos buscando.
Con las cintas magnéticas empezó lo que con el tiempo sería el acceso
aleatorio a los datos. Se podía reservar parte de la cinta para guardar cierta
información sobre la situación de los datos, y añadir ciertas marcas que
hicieran más sencillo localizarla.
Pero no fue hasta la aparición de los discos magnéticos cuando ésta
técnica llegó a su apogeo. En los discos es más sencillo acceder a cualquier
punto de la superficie en poco tiempo, ya que se accede al punto de lectura y
escritura usando dos coordenadas físicas. Por una parte la cabeza de
lectura/escritura se puede mover en el sentido del radio del disco, y por otra
el disco gira permanentemente, con lo que cualquier punto del disco pasa por la
cabeza en un tiempo relativamente corto. Esto no pasa con las cintas, donde
sólo hay una coordenada física.
Con la invención y proliferación de los discos se desarrollaron los
archivos de acceso aleatorio, que permiten acceder a cualquier dato
almacenado en un archivo en relativamente poco tiempo.
Actualmente, los discos duros tienen una enorme capacidad y son muy
rápidos, aunque aún siguen siendo lentos, en comparación con las memorias
RAM. El caso de los CD es algo intermedio. En realidad son secuenciales en
cuanto al modo de guardar los datos, cada disco sólo tiene una pista de datos
grabada en espiral. Sin embargo, este sistema, combinado con algo de memoria
RAM, proporciona un acceso muy próximo al de los discos duros.

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

Los archivos son estructuras de datos de carácter permanente, residen


en memoria secundaria a diferencia de lo que habíamos visto anteriormente,
que residen en memoria principal. La principal ventaja de trabajar con archivos
es que se pueden almacenar datos con un programa y una vez finalizada la
sesión, se puede en otra oportunidad acceder a dichos datos, a diferencia de
las otras estructuras que pierden los datos al salir o reiniciar la máquina.
En cuanto al tipo de acceso, en C y C++ podemos clasificar los archivos
según varias categorías:
1.- Dependiendo de la dirección del flujo de datos:
• De entrada: los datos se leen por el programa desde el archivo.
• De salida: los datos se escriben por el programa hacia el archivo.
• De entrada/salida: los datos pueden se escritos o leídos.
2.- Dependiendo del tipo de valores permitidos a cada byte:
• De texto: sólo están permitidos ciertos rangos de valores para
cada byte. Algunos bytes tienen un significado especial, por ejemplo, el
valor hexadecimal 0x1A marca el fin de archivo. Si abrimos un archivo en
modo texto, no será posible leer más allá de ese byte, aunque el archivo
sea más largo.
• Binarios: están permitidos todos lo valores para cada byte. En
estos archivos el final del archivo se detecta de otro modo, dependiendo
del soporte y del sistema operativo. La mayoría de las veces se hace
guardando la longitud del archivo. Cuando queramos almacenar valores
enteros, o en coma flotante, o imágenes, etc, deberemos usar este tipo
de archivos.
3.- Según el tipo de acceso:
• Archivos secuenciales: imitan el modo de acceso de los antiguos
archivos secuenciales almacenados en cintas magnéticas y
• Archivos de acceso aleatorio: permiten acceder a cualquier punto
de ellos para realizar lecturas y/o escrituras.
4.- Según la longitud de registro:
• Longitud variable: en realidad, en este tipo de archivos no tiene
sentido hablar de longitud de registro, podemos considerar cada byte
como un registro. También puede suceder que nuestra aplicación conozca
el tipo y longitud de cada dato almacenado en el archivo, y lea o escriba
los bytes necesarios en cada ocasión. Otro caso es cuando se usa una
marca para el final de registro, por ejemplo, en archivos de texto se usa
el carácter de retorno de línea para eso. En estos casos cada registro es
de longitud diferente.

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

• Longitud constante: en estos archivos los datos se almacenan en


forma de registro de tamaño constante. En C usaremos estructuras para
definir los registros. C dispone de funciones de librería adecuadas para
manejar este tipo de archivos.
• Mixtos: en ocasiones pueden crearse archivos que combinen los
dos tipos de registros, por ejemplo, dBASE usa registros de longitud
constante, pero añade un registro especial de cabecera al principio para
definir, entre otras cosas, el tamaño y el tipo de los registros.

Resumiendo, existen 2 tipos de archivos que son:


• Archivos de Texto: Tienen un procesamiento secuencial y están incluidos
todos los caracteres ASCII ej:datos.txt.
• Archivos Binarios: Tienen un procesamiento secuencial y aleatorio, se
basan en registros de tipo struct ej: suma.exe.

Operaciones Básicas.
1.- Actualización: Están contenidas tres operaciones en esta categoría:
agregar, eliminar y modificar archivos.
2.- Búsqueda: Una vez creado un archivo, se puede acceder a los datos
contenidos buscando por algún campo genérico.
3.- Pareamiento: Es encontrar una relación o un campo en común entre
los registros de un archivo A en otro archivo B.
4.- Intercalación: Es entrelazar dos archivos en un tercer archivo
respetando los criterios y formatos.
5.- Clasificación: Es ordenar un archivo por algún campo genérico.
Generalmente los cambios se hacen sobre otro archivo de texto.
6.- Concatenación: Es unir dos archivos de texto con igual formato.
Cuando se trabaja con archivos, se hace con flujos de datos que se transfieren
entre el usuario y el archivo y existen dos tipos de flujos correspondientes a
cada tipo de archivo.
(a) Flujo de texto (secuencia de caracteres con formato).
(b) Flujo binario (secuencia de bytes, datos no textuales).
Es posible crear archivos combinando cada una de estas categorías, por
ejemplo: archivos secuenciales de texto de longitud de registro variable, que
son los típicos archivos de texto. Archivos de acceso aleatorio binarios de
longitud de registro constante, normalmente usados en bases de datos. Y
también cualquier combinación menos corriente, como archivos secuenciales
binarios de longitud de registro constante, etc.
Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)
web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

Apuntadores o Punteros a Archivos


Para poder hecer referencia a un archivo se necesitan punteros que
hagan referencia a la linea del archivo donde se está trabajando. De esta
manera podemos guiar el flujo de datos a cierta posición dentro del archivo y
así poder posicionarnos en cualquierparte del archivo por medio del puntero.
Para declarar un puntero a un archivo en C++, su estructura es la
siguiente:
FILE *stream;
Donde stream (flujo en inglés) es un puntero que tiene la capacidad de
apuntar a un archivo.

Como Abrir Archivos.


En cuanto a cómo se definen estas propiedades, hay dos casos. Si son
binarios o de texto o de entrada, salida o entrada/salida, se define al abrir el
archivo, mediante la función fopen:
La función open usa dos parámetros. El primero es el nombre del archivo
que contiene el archivo. El segundo es el modo que es una cadena que indica el
modo en que se abrirá el archivo: lectura o escritura, y el tipo de datos que
contiene: de texto o binarios, ejemplo:
stream = fopen (“datos.txt”,”wt”)
Ahora stream está apuntando al archive datos.txt que es un archivo de
texto abierto en modo wt.

Modos Para Abrir Archivos.


En C, los archivos admiten doce modos en cuanto a la dirección del flujo
de datos, formados por la combinación de seis letras que se mensionan a
continuación:
r(read): modo lectura.
w(write): modo escritura.
a(append): modo agregar.
+(update): modo actualización
t: modo texto. Normalmente es el modo por defecto. Se suele omitir.
b: modo binario.
Las doce combinaciones existentes son:

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

r Abre un archivo de texto existente para lectura


w Crea un archivo de texto para escribir
Abre o crea un archivo de texto para escribir al final del
a
archivo y añadir información(EOF)
rb Abre un archivo en modo binario existente para lectura
wb Crea un archivo en modo binario para escribir
Abre o crea un archivo en modo binario para escribir al final
ab
del archivo y añadir información(EOF)
Abre un archivo de texto para actualización (lectura y
r+
escritura)
w+ Crea un archivo de texto para actualización
Abre o crea un archivo de texto para actualización, escribiendo
a+
al final del archivo y añadir información (EOF)
Abre un archivo en modo binario para actualización (lectura y
r+b ó rb+
escritura)
w+b ó Trunca, a longitud cero o crea un archivo en modo binario para
wb+ actualización
Abre o crea un archivo en modo binario para actualización,
a+b ó ab+
escribiendo al final del archivo y añadir información (EOF)

Ejemplo:
#include <stdio.h>

int main()
{
FILE *fichero;
char nombre[10] = "datos.dat";

fichero = fopen( nombre, "w" );


printf( "Fichero: %s -> ", nombre );
if( fichero )
printf( "creado (ABIERTO)\n" );
else
{
printf( "Error (NO ABIERTO)\n" );
return 1;
}

if( !fclose(fichero) )
printf( "Fichero cerrado\n" );
else
{
printf( "Error: fichero NO CERRADO\n" );
return 1;
}

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

return 0;
}

Cerrar Archivos.
Para cerrar archivos se usa el commando fclose, el cual lleva como
parámetro el puntero al archivo. Es importante cerrar los ficheros abiertos
antes de abandonar la aplicación. Esta función sirve para eso. Cerrar un fichero
almacena los datos que aún están en el buffer de memoria, y actualiza algunos
datos de la cabecera del fichero que mantiene el sistema operativo. Además
permite que otros programas puedan abrir el fichero para su uso. Muy a
menudo, los ficheros no pueden ser compartidos por varios programas.
Un valor de retorno cero indica que el fichero ha sido correctamente
cerrado, si ha habido algún error, el valor de retorno es la constante EOF. El
parámetro es un puntero a la estructura FILE del fichero que queremos
cerrar.
Ejemplo:
fclose(stream);

Comando EOF
Sirve para indicar o referenciar el fin de un archivo ejemplo:
While(stream!= EOF)
{…
}
Comando fgetc
Esta función lee un carácter desde un fichero.
El valor de retorno es el carácter leído como un unsigned char
convertido a int. Si no hay ningún carácter disponible, el valor de retorno es
EOF. El parámetro es un puntero a una estructura FILE del fichero del que se
hará la lectura.
Ejemplo:
#include <string.h>
#include <stdio.h>
#include <conio.h>

void main()
{
FILE *stream;
char string[] = "Esto es una prueba";
char ch;

/* crea un archivo para escribir y actualizar*/


stream = fopen("DUMMY.FIL", "w+");
Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)
web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

/* escribe un string en el archivo*/


fwrite(string, strlen(string), 1, stream);

/* se posiciona al principio del archivo */


fseek(stream, 0, SEEK_SET);

do
{
/* lee un caracter del archivo */
ch = fgetc(stream);

/* muestra el caracter */

putch(ch);
} while (ch != EOF);

fclose(stream);
}

Comando fputc
Esta función escribe un carácter a un fichero.
El valor de retorno es el carácter escrito, si la operación fue completada
con éxito, en caso contrario será EOF. Los parámetros de entrada son el
carácter a escribir, convertido a int y un puntero a una estructura FILE del
fichero en el que se hará la escritura.
Ejemplo:

#include <stdio.h>

void main()
{
char msg[] = "Hola mundo";
int i = 0;

while (msg[i])
{
fputc(msg[i], stdout);
i++;
}

Comando feof
Esta función sirve para comprobar si se ha alcanzado el final del fichero.
Muy frecuentemente deberemos trabajar con todos los valores almacenados en
un archivo de forma secuencial, la forma que suelen tener los bucles para leer
todos los datos de un archivo es permanecer leyendo mientras no se detecte el

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

fin de fichero. Esta función suele usarse como prueba para verificar si se ha
alcanzado o no ese punto.
El valor de retorno es distinto de cero sólo si no se ha alcanzado el fin
de fichero. El parámetro es un puntero a la estructura FILE del fichero que
queremos verificar.
Ejemplo:
#include <stdio.h>
void main()
{
FILE *stream;

/* abre un archivo para lectura */


stream = fopen("DUMMY.FIL", "r");

/* lee un caracter del archivo */


fgetc(stream);

/* chequea si es el fin del archivo */


if (feof(stream))
printf("Estamos en el fin del archivo\n");

/* cerrando el archivo */
fclose(stream);

Comando fprintf
Esta función envía datos al stream apuntado por stream, bajo el control
de la cadena apuntada por formato que especifica cómo los argumentos
posteriores son convertidos para la salida. Si hay argumentos insuficientes
para el formato, el comportamiento no está definido. Si el formato termina
mientras quedan argumentos, los argumentos restantes son evaluados (como
siempre) pero ignorados. La función retorna control cuando el final de la
cadena de formato es encontrado.
Ejemplo:

fprintf( fichero, "Esto es un ejemplo de usar la funcion \'fprintf\'\n"


);

Comando fsanf
Esta función recibe datos del stream apuntado por stream, bajo el
control de la cadena apuntada por el formato que especifica las secuencias de
entrada permitadas y cómo han de ser convertidas para la asignación. Si hay

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

argumentos insuficientes para el formato, el comportamiento no está definido.


Si el formato termina mientras quedan argumentos, los argumentos restantes
son evaluados (como siempre) pero ignorados. La función retorna control
cuando el final de la cadena de formato es encontrado.
Ejemplo:
#include <stdlib.h>
#include <stdio.h>

void main()
{
int i;

printf("Ingresa un entero: ");

/* lee un entero de
el flujo estandar */
if (fscanf(stdin, "%d", &i))
printf("El entero leido fue: %i\n", i);
else
{
fprintf(stderr, "Error de lectura de entero de stdin.\n");
exit(1);
}

Comando fseek
La función fseek activa el indicador de posición de ficheros para el
stream apuntado por stream. Para un stream binario, la nueva posición, medido
en caracteres del principio del fichero, es obtenida mediante la suma de
desplazamiento y la posición especificada por origen. La posición especificada
es el comienzo del fichero si origen es SEEK_SET, el valor actual del indicador
de posición de fichero si es SEEK_CUR, o final de fichero si es SEEK_END. Un
stream binario realmente no necesita soportar llamadas a fseek con un valor de
origen de SEEK_END. Para un stream de texto, o bien desplazamiento será
cero, o bien desplazamiento será un valor retornado por una llamada anterior a
la función ftell al mismo stream y origen será SEEK_SET. Una llamada
correcta a la función fseek despeja el indicador de final de fichero para el
stream y deshace cualquier efecto producido por la función ungetc en el mismo
stream. Después de una llamada a fseek, la siguiente operación en un stream de
actualización puede ser de entrada o salida.
Ejemplo: fseek( fichero, 0L, SEEK_END );

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com
Programación Estructurada

Comando ftell
La función fseek obtiene el valor actual del indicador de posición de
fichero para el stream apuntado por stream. Para un stream binario, el valor es
el número de caracteres desde el principio del fichero. Para un stream de
texto, su indicador de posición de fichero contiene información no
especificado, servible a la función fseek para retornar el indicador de posición
de fichero para el stream a su posición cuando se llamó a ftell; la diferencia
entre los dos valores de retorno no es necesariamente una medida real del
número de caracteres escritos o leídos.
Ejemplo:
f = ftell( stream );
fseek( stream, f, SEEK_SET );

Juan Carlos Gonzalez Ulloa (ayudante programacion estructurada)


web: www.ayudantiaprogramacion.googlepages.com, mail: ayudantiaprogramacion@gmail.com