Unidad 7 - Computacion Avanzada

Anuncio
Unidad 7 1
Computación Avanzada
Entrada y Salida de Datos. Lectura de archivos.
Son innumerables los casos en los que son necesarios guardar datos entre ejecuciones de
un programa para poder ser recuperados en futuras sesiones. Los archivos de datos
permiten almacenar información de cualquier tipo de modo permanente para ser
accedida o alterada cuando sea necesario.
En C existe un conjunto extenso de funciones de biblioteca para crear y procesar archivos
de datos. Los archivos secuenciales de datos se pueden dividir en dos categorías. En la
primera categoría están los archivos que contienen caracteres consecutivos. Estos
caracteres se pueden interpretar como datos individuales, como componentes de una
cadena o como números. La segunda categoría es a menudo denominada archivos sin
formato y organiza los datos en bloques contiguos de información. Estos bloques
representan estructuras de datos más complejas como arrays y estructuras ( struct ).
Cuando se trabaja con archivos secuenciales de datos, el primer paso es establecer un
área de buffer, donde la información se almacena temporalmente mientras se está
transfiriendo entre la memoria y el archivo de datos. Esta área de buffer permite leer y
escribir información del archivo más rápidamente de lo que sería posible de otra manera.
El área de buffer se establece escribiendo:
FILE *ptvar;
Donde FILE es un tipo de estructura que establece el área de buffer y ptvar la variable
puntero ( puntero a archivo ) que indica el comienzo de este área. El tipo de estructura
FILE está definido en stdio.h. Aquí, a ptvar se le conoce como un flujo lo cual es un
dispositivo lógico resultado de la transformación de un archivo con buffer. Esto crea un
nivel abstracción que nos permite trabajar de igual forma con cualquier dispositivos
aunque éstos sean diferentes.
Al principio de la ejecución de un programa se abren cinco flujos de texto predefinidos. Se
trata de stdin, stdout, stderr, stdaux y stdprn, y se refieren a los dispositivos de E/S
estándar conectados al sistema para teclado, pantalla, errores por pantalla, primer puerto
serie e Impresora respectivamente. Los dos últimos son específicos de Turbo C por lo que
pueden no ser transportables a otros compiladores.
El sistema de archivos ANSI C se compone de varias funciones interrelacionadas. Las más
comunes son:
fopen(): Abre un flujo.
fclose(): Cierra un flujo.
putc(): Escribe una carácter en un flujo.
Unidad 7 2
Computación Avanzada
getc(): Lee un carácter de un flujo.
fseek(): Busca un byte específico en un flujo.
fprintf(): Hace lo mismo en flujos que printf() en consola.
fscanf(): Hace lo mismo en flujos que scanf() en consola.
feof(): Devuelve cierto si ha llegado al final del archivo.
rewind(): Coloca el localizador de posición del archivo al principio del mismo.
remove(): Elimina un archivo.
Un archivo de datos debe ser abierto antes de ser creado o procesado. Esto asocia el
nombre del archivo con el área de buffer. También se especifica cómo se va a usar el
archivo.
Para abrir un archivo se usa la función fopen():
ptvar = fopen ( nombre_archivo, tipo_archivo);
donde nombre_archivo y tipo_archivo son cadenas. Los tipos de archivo y su significado
son:
"r": Abrir un archivo existente sólo para lectura.
"w": Abrir un nuevo archivo sólo para escritura. Si ya existe, será destruido y
creado uno nuevo en su lugar.
"a": Abrir un archivo para añadir. Si no existe, se crea uno nuevo.
"r+": Abrir un archivo existente para lectura y escritura.
"w+": Abrir un archivo nuevo para lectura y escritura. Si ya existe, será destruido y
creado uno nuevo en su lugar.
"a+": Abrir un archivo existente para leer y añadir. Si no existe, se crea uno nuevo.
Unidad 7 3
Computación Avanzada
La función fopen() retorna un puntero al principio del área de buffer asociada con el
archivo. Se retorna un valor NULL si no se puede abrir el archivo.
Un archivo de datos debe cerrarse al final del programa o cuando ya no sea necesario
mantenerlo mas tiempo abierto. Esto se realiza a través de:
fclose(ptvar);
Un archivo secuencial de datos puede crearse de dos formas distintas. Una es crear el
archivo directamente, usando un editor. La otra es escribir un programa que introduzca
información en la computadora y la escriba en un archivo. Los archivos sin formato sólo
pueden crearse mediante programas.
Cuando se crea un archivo con un programa, lo habitual es introducir la información desde
el teclado y escribirla en el archivo.
Si el archivo consta de caracteres individuales, se pueden usar la funciones getchar() ( para
obtener caracteres de teclado ) y putc() ( para escribir caracteres en un archivo ). El uso de
putc() es el siguiente:
putc(variable_de_tipo_caracter,puntero_al_area_de_buffer);
Un archivo creado de esta manera puede ser visualizado de distintas formas: usando un
orden del sistema operativo tal como type, usando un editor o escribiendo un programa
que lea el contenido y lo muestre. Para ello se pueden utilizar las funciones getc() ( lee
caracteres de un archivo ) y putchar() ( para escribir caracteres por pantalla ). El uso de
getc() es:
variable_de_tipo_caracter=getc (puntero_al_area_de_buffer);
Los archivos de datos que contienen sólo cadenas de caracteres pueden crearse y leerse
más fácilmente con programas que utilizan funciones de biblioteca especialmente
orientadas para cadenas: fgets() y fputs().
Muchos archivos de datos contienen estructuras de datos más complicadas ( como las
struct ) que incluyen combinaciones de información, caracteres y números. Tales archivos
se pueden procesar usando las funciones fscanf() y fprintf():
fprintf(puntero_area_buffer,cadena_control,argto1,..,argton);
fscanf(puntero_area_buffer,cadena_control,&argto1,..,&argton);
Unidad 7 4
Computación Avanzada
Una vez creado un archivo de datos surge la pregunta de cómo detectar una condición de
fin de archivo. La función feof() sirve para este propósito ( válida para un archivo
secuencial con o sin formato ). Esta función devuelve un valor distinto de cero ( cierto ) si
detecta una condición de fin de archivo y un valor cero ( falso ) si no se detecta.
Para actualizar los registros dentro de un archivo de datos hay varios enfoques. Uno de
ellos consiste en leer cada registro del archivo, actualizarlo y escribirlo en el mismo
archivo. Sin embargo es difícil leer y escribir datos con formato al mismo archivo sin
alterar la ordenación de los elementos dentro del archivo. Otro enfoque es trabajar con
dos archivos diferentes: un archivo antiguo ( la fuente ) y otro nuevo. Se lee cada registro
del archivo antiguo, se actualiza y se escribe en el archivo nuevo.
Algunas aplicaciones implican el uso de archivos para almacenar bloques de datos, donde
cada bloque consiste en un número fijo de bytes contiguos. Cada bloque representará
generalmente una estructura de datos compleja, como una struct o un array. Para estas
aplicaciones sería deseable leer o escribir el bloque entero del archivo de datos en vez de
leer o escribir separadamente las componentes individuales de cada bloque. Las funciones
fread() y fwrite() deben usarse en estas situaciones. A estas funciones se las conoce como
funciones de lectura y escritura sin formato. Igualmente se hace referencia a estos
archivos de datos como archivos de datos sin formato.
Cada una de estas funciones necesita cuatro argumentos:
- la dirección del bloque de datos
- el tamaño del bloque de datos
- el número de bloques a transferir
- el puntero a un archivo secuencial
Ejemplo:
fwrite(&cliente, sizeof(struct ejemplo), 1, ptvar);
fread(&cliente, sizeof(struct ejemplo), 1, ptvar);
Unidad 7 5
Computación Avanzada
Donde cliente es una variable estructura de tipo “struct ejemplo” y ptvar un puntero a
archivo secuencial.
Utilizando el sistema de E/S con buffer se pueden realizar operaciones de lectura y
escritura directa con la ayuda de fseek(), que sitúa el indicador de posición del archivo. Su
prototipo es:
int fseek(FILE *pa, long num_bytes, int origen );
Donde pa es un puntero a archivo devuelto por una llamada fopen(); num_bytes es un
entero largo que representa el número de bytes a partir del “origen” que supondrán la
nueva posición y origen es una de las siguientes macros definidas en stdio.h:
SEEK_SET Principio del archivo ( valor de cero )
SEEK_CUR Posición actual ( valor de uno )
SEEK_END Final del archivo ( valor de dos )
Veamos un ejemplo donde pondremos en práctica varios de estos conceptos.
/* Programa de acceso a archivos; escritura, agregado y lectura de líneas */
#include <stdio.h>
#define MAXLINEA 100
int main() {
char n_arch[] = "Archivo.dat"; /* nombre archivo de datos */
char n_prog[] = "Archivo.c"; /* nombre del programa, para error */
char mensaje[] = "Esta es una linea de prueba.\n";
char linea[MAXLINEA]; /* para lectura */
FILE *pa; /* puntero al archivo */
int i = 0;
printf("\n\nAcceso a archivos.\n");
Unidad 7 6
Computación Avanzada
/* reescribe o crea el archivo, agrega una línea */
if ((pa = fopen(n_arch, "w")) == NULL) {
printf("%s: no se puede abrir archivo %s", n_prog, n_arch);
return 1; /* error, no pudo abrir el archivo */
} else {
fputs(mensaje, pa); /* graba línea en archivo */
fclose(pa);
printf("Grabó línea en archivo.\n");
}
/* lectura del archivo, una línea */
pa = fopen(n_arch, "r");
fgets(linea, MAXLINEA, pa); //c har *fgets(char *buffer, int tamano, FILE *archivo);
fclose(pa);
printf("Leyó línea: %s", linea);
/* agrega una línea al archivo */
pa = fopen(n_arch, "a");
strcpy(linea, "Esta es una línea agregada al archivo.\n");
fputs(linea, pa);
fclose(pa);
printf("Agregó linea al archivo.\n");
Unidad 7 7
Computación Avanzada
/* lee líneas del archivo hasta terminar */
printf("Lectura de varias líneas:\n");
pa = fopen(n_arch, "r");
while ( fgets(linea, MAXLINEA, pa) != NULL ) {
printf("Línea %i: %s", ++i, linea);
}
fclose(pa);
printf("Fin de pruebas de acceso a archivos.\n");
return 0;
}
Otro ejemplo:
#include<stdio.h>
void main(void) {
char ch;
FILE *fp;
// Entrada desde Archivo en DISCO
printf("Entrada desde archivo.\n");
if (!(fp = fopen ("Archivo.c", "r"))) {
printf("No se puede abrir Archivo.c\n");
} else {
Unidad 7 8
Computación Avanzada
fflush(fp); // Vacía el contenido de una secuencia de salida
while ((ch != EOF)) {
ch = getc(fp);
printf("%c", ch);
}
fclose(fp);
}
}
Descargar