Estructuras de Archivos ING. YIM ISAIAS APESTEGUI FLORENTINO Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 1 Desbordamiento de búfer En seguridad informática y programación, un desbordamiento de buffer (del inglés buffer overflow o buffer overrun) es un error de software que se produce cuando se copia una cantidad de datos sobre un área que no es lo suficientemente grande para contenerlos, sobrescribiendo de esta manera otras zonas de memoria. Esto se debe en general a un fallo de programación. La consecuencia de escribir en una zona de memoria imprevista puede resultar impredecible. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 2 Existen zonas de memoria protegidas por el sistema operativo. Si se produce la escritura fuera de una zona de memoria protegida se producirá una excepción del sistema de acceso a memoria seguido de la terminación del programa. Bajo ciertas condiciones, un usuario obrando con malas intenciones puede aprovecharse de este mal funcionamiento o una vulnerabilidad para tener control sobre el sistema. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 3 Si el programa que tiene el error en cuestión tiene privilegios especiales se convierte además en un fallo de seguridad. El código copiado especialmente preparado para obtener los privilegios del programa atacado se llama shellcode. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 4 Un desbordamiento de búffer ocurre cuando los datos que se escriben en un búffer corrompen aquellos datos en direcciones de memoria adyacentes a los destinados para el búffer, debido a una falta de validación de los datos de entrada. Esto se da comúnmente al copiar cadenas de caracteres de un búffer a otro. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 5 Ejemplo básico En este ejemplo, un programa tiene definidos dos elementos de datos continuos en memoria: un buffer de 8 bytes tipo string, A, y otro de dos bytes tipo entero, B. Al comienzo, A contiene bytes nulos y B contiene el número 3 (cada carácter se representa mediante un byte). 0 0 0 0 0 0 Buffer A Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 0 0 0 3 Buffer B 6 A continuación, el programa intenta almacenar la cadena de caracteres "demasiado" en el buffer A, seguido de bytes nulos para marcar el fin de string. Al no validarse la longitud de la cadena, se sobrescribe el valor de B: 'd' 'e' 'm' 'a' 's' 'i' Buffer A Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 'a' 'd' 'o' 0 Buffer B 7 A pesar de que el programador no quería cambiar el contenido del búffer B, el valor de éste ha sido reemplazado por un número equivalente a parte de la cadena de caracteres. Para este ejemplo, en un sistema big-endian que use ASCII, el carácter 'o' seguido del byte nulo equivale al número 28416. Si B fuese la única variable aparte de A definida en el programa, la escritura de datos que sobrepasen los límites de B generarían un error como segmentation fault, concluyendo así el programa. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 8 RECORDANDO… La función strcpy: char *strcpy (char *cadena1, const char *cadena2); //Prototipo de strcpy Sirve para copiar la cadena cadena2 dentro de cadena1. Devuelve el valor de cadena1. strcpy recibe dos parámetros: un apuntador a char (modificable), y un apuntador a char constante. Y devuelve un apuntador a char. La funcion strncpy: La función strncpy: char *strncpy (char *cadena1, const char *cadena2, size_t n) Sirve para copiar n caracteres de cadena2 hacia cadena1. Devuelve el valor de cadena1. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 9 Código fuente de ejemplo En el siguiente ejemplo se presenta un código fuente en C con un error de programación. Una vez compilado, el programa generará un desbordamiento de buffer si se lo invoca desde la línea de comandos con un argumento lo suficientemente grande, pues este argumento se usa para llenar un buffer, sin validar previamente su longitud /* overflow.c - demuestra un desbordamiento de buffer */ #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { char buffer[10]; if (argc < 2) { fprintf(stderr, "MODO DE USO: %s string\n", argv[0]); return 1; } strcpy(buffer, argv[1]); return 0; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 10 Strings de 9 caracteres o menos no provocarán desbordamiento de buffer. Por el contrario, strings de 10 caracteres o más sí: esto siempre es incorrecto, aunque no siempre resultará en un error del programa o segmentation fault. /* mejor.c - demuestra un método de resolver el problema */ #include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { char buffer[10]; if (argc < 2) { fprintf(stderr, "MODO DE USO: %s string\n", argv[0]); return 1; } strncpy(buffer, argv[1], sizeof(buffer)); buffer[sizeof(buffer) - 1] = '\0'; return 0; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 11 1. Problema: En la vida real es necesario agrupar con frecuencia datos de distintos tipos: por ejemplo, el documento nacional de identidad contiene, entre otros, un entero (el número) y cadenas de caracteres (el nombre, los apellidos, etc.);. Solución: Los registros permiten crear estructuras que pueden contener entidades de distinto tipo, formando así, un árbol de estructuras y subestructuras de datos. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 12 2. Definición de registro. Un registro (record) es un tipo de datos estructurado (denominado dato record) que consta de un conjunto de elementos que pueden ser del mismo tipo o de tipos diferentes. Los componentes de un registro se denominan campos. Cada campo tiene un nombre llamado identificador de campo, que es algún identificador elegido por el programador cuando se declara el tipo de registro y un tipo que se especifica cuando se declara el tipo de dato record. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 13 3. Registros en ANSI C. La forma de definir registros en C es mediante el uso de estructuras. Una estructura es una colección de uno o más tipo de elementos denominados miembros, cada uno de los cuales puede ser de un tipo de dato diferente. 4. Declaración de estructuras. Struct <nombre> { <tipo-1> <variable-1>; <tipo-2> <nombre-2>; ……………………. <tipo-n> <nombre-n>; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 14 5. Ejemplo de Declaración de una estructura. Struct Musica_Cds { char titulo[16]; char artista[30]; int canciones; int precio; char fecha_compra[8]; }; Struct complejo { float parte_real, parte_imaginaria; }; Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 15 6. Definición de variables de Estructuras. La declaración anterior, solo indica el nombre de un estructura y sus campos componentes. Para asignar un área de memoria de tipo estructura, es necesario definir una variable. Para definir una variable, existen dos formas: a) Listando los nombres de las variables a continuación de la estructura. struct musica_cds { char titulo[16]; char artista[30]; int canciones; int precio; char fecha_compra[8]; } cd1 cd2, cd3; b) Listando el nombre de la estructura seguida por los nombres de las variables en cualquier lugar del programa. struct musica_cds cd1,cd2,cd3; (En C++ no se requiere la palabra struct) Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 16 7. Asignación de estructuras. Las variables estructuras se pueden asignar directamente entre ellas produciéndose un movimiento de cada una de sus componentes. La asignación directa de variables struct requiere que ambas variables estén definidas bajo la misma estructura. Ejemplos: struct musica_cds { char titulo[16]; char artista[30]; int canciones; int precio; char fecha_compra[8]; } cd1 cd2, cd3; cd1=c2; cd1=cd2=cd3; Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 17 8. Inicialización de estructuras. Las variables estructuras se pueden inicializar de dos formas: En cualquier parte de la sección de código del programa o bien en la declaración o en la definición de la estructura. El formato es el siguiente: struct <nombre_variable> {valor-1,valor-2,….,valor-n}; El formato de inicialización anterior, asigna a los miembros de la estructura cada uno de los valores separados por coma y entre llaves. Debe existir una concordancia en tipo y cantidad de datos asignados. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 18 Ejemplo: struct musica_cds { char titulo[50]; char artista[30]; int canciones; int precio; char fecha_compra[8]; } cd1={"Diamantes y Oxidos","Joan Baez", 18,25000,"20080701"}, cd2, cd3; struct complejos {float real, imaginario; }; struct musica_cds x; struct complejos z1= {41,25}, z2; int main() { cd3= cd2= cd1; printf("%s\n", cd1.titulo); printf("%s\n", cd2.titulo); printf("%s\n", cd3.titulo); printf("%f %f\n", z1.real, z1.imaginario); } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 19 9. Acceso a estructuras. 9.1. Almacenamiento de información en estructuras. Se puede almacenar información en una estructura mediante inicialización, asignación o lectura. Formato para acceder a los campos: <nombre_variable> . <nombre_miembro> = <valor>; Ejemplo asignación: struct musica_cds { char titulo[50]; char artista[30]; int canciones; int precio; char fecha_compra[8]; } cd1,cd2,cd3; int main() { strcpy(cd1.titulo,"Diamantes y Oxidos"); strcpy(cd1.artista,"Joan Baez"); cd1.canciones=18; cd1.precio=25000; strcpy(cd1.fecha_compra,"20080701"); } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 20 Ejemplo Letura: struct musica_cds { char titulo[50]; char artista[30]; int canciones; int precio; char fecha_compra[8]; } cd1,cd2,cd3; void main() { printf("Ingrese printf("Ingrese printf("Ingrese printf("Ingrese printf("Ingrese titulo:"); scanf("%s",cd1.titulo); artista:"); scanf("%s", cd1.artista); canciones:"); scanf("%d", &cd1.canciones); precio:"); scanf("%d", &cd1.precio); fecha de compra:"); scanf("%s", cd1.fecha_compra); } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 21 9.2. Recuperación de información desde estructuras. La información contenida en una estructura se recupera usando la asignación o bien imprimiendo los miembros de una estructura. En ambos casos se debe usar el operador punto para referenciar los miembros. Ejemplo: struct musica_cds { char titulo[50]; char artista[30]; int canciones; int precio; char fecha_compra[8]; } cd1,cd2,cd3; void main() { printf("Ingrese titulo:"); scanf("%s",cd1.titulo); printf("Ingrese artista:"); scanf("%s", cd1.artista); printf("Ingrese canciones:"); scanf("%d", &cd1.canciones); printf("Ingrese precio:"); scanf("%d", &cd1.precio); printf("Ingrese fecha de compra:"); scanf("%s", cd1.fecha_compra); cd2=cd1; cd2.precio=cd2.precio+1000; printf("Titulo:%s\n",cd2.titulo); printf("Artista:%s\n",cd2.artista); printf("Canciones:%d\n",cd2.canciones); printf("Precio:%d\n",cd2.precio); printf("Fecha Compra:%s\n",cd2.fecha_compra); } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 22 9.3. Estructuras como punteros. Las estructuras es posible operarlas como punteros utilizando ya sea el operador de indirección o bien el operador de puntero(->). Ejemplo: #include <stdio.h> #include <stdlib.h> const n=10; struct datos { char nombre[40]; int edad; }; void main() { struct datos alumno1; struct datos *alumno2; alumno2=&alumno1; strcpy((*alumno2).nombre,"Juan"); alumno1.edad=45; printf("Nombre: %s\n",(*alumno2).nombre); printf("Edad: %d\n",alumno2->edad); strcpy(alumno2->nombre,"Pedro"); alumno2->edad=55; printf("Nombre: %s\n",alumno2->nombre); printf("Edad: %d\n",(*alumno2).edad); system("PAUSE"); return 0; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 23 10 Anidamiento de estructuras. Una estructura puede contener como miembro otras estructuras en forma anidada, para diferenciar los campos se requiere el uso de múltiples operadores punto. Ejemplo: struct dir { char calle[40]; int numero; char comuna[50];}; struct fecha { int dia, mes, ano; }; struct registro_personal { char nombre[50]; struct dir direccion; }; struct registro_empleado { struct registro_personal dpersonales ; struct fecha fecha_contrato; long sueldo; } e1; int main() { strcpy(e1.dpersonales.nombre,"Juan"); e1.dpersonales.direccion.numero=3342; e1.fecha_contrato.dia=2; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 24 11 Arreglos de estructuras y estructuras de arreglos. Es posible crear arreglos cuyos elementos son estructuras y a la vez una estructura puede contener ente sus miembros arreglos de distinto tipo. El acceso a un elemento se hace usando la notación de arreglos (fila, columna, etc.) y la notación punto. Ejemplo: const n=10; struct registro_alumnos { char nombre[100]; int certamen[3]; }; void main() { struct registro_alumnos curso[n]; int i , j; float promedio; for (i=0;i< n;i++) { printf("%d Ingrese nombre:",i); scanf("%s",curso[i].nombre); for (j=0;j<3;j++) { printf("%d Ingrese certamen numero %d:",i,j); scanf("%d",&curso[i].certamen[j]); } } for (i=0;i<n;i++) { promedio=0; for (j=0;j<3;j++) promedio+=curso[i].certamen[j]; promedio/=3; printf("Alumno %d, promedio:%f\n",i,promedio); } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 25 12 Creación de tipos: Operador Typedef. El operador TypeDef permite crear un nombre sinónimo de un tipo de dato ya existente que facilita la creación de variables. Ejemplo: Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 26 13 Arreglos de estructuras y estructuras de arreglos. Es posible crear arreglos cuyos elementos son estructuras y a la vez una estructura puede contener ente sus miembros arreglos de distinto tipo. El acceso a un elemento se hace usando la notación de arreglos (fila, columna, etc.) y la notación punto. Ejemplo: const n=10; struct registro_alumnos { char nombre[100]; int certamen[3]; }; void main() { struct registro_alumnos curso[n]; int i , j; float promedio; for (i=0;i< n;i++) { printf("%d Ingrese nombre:",i); scanf("%s",curso[i].nombre); for (j=0;j<3;j++) { printf("%d Ingrese certamen numero %d:",i,j); scanf("%d",&curso[i].certamen[j]); } } for (i=0;i<n;i++) { promedio=0; for (j=0;j<3;j++) promedio+=curso[i].certamen[j]; promedio/=3; Organizacion de Archivos: Ing. Yim printf("Alumno %d, promedio:%f\n",i,promedio); Isaias Apestegui Florentino } 27 14. Archivos. Un archivo es una colección de datos que son almacenados de manera estructurada, cuyas entidades poseen ciertos aspectos en común y se encuentran organizados para algún propósito. Carpetas: Conjunto de carpetas y archivos Archivos Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 28 Características. Hasta el momento hemos trabajado con estructuras de datos que se almacenan en memoria principal. Cuando el programa termina, se pierden todos los datos. Los archivos son estructuras que permiten almacenar información en forma permanente en memoria secundaria (disco duro, Pen-drive, etc.). Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 29 Usos de archivos. La entrada y salida estándar de datos (teclado y pantalla) pueden ser reemplazado por el uso de archivos. Los programas pueden utilizan archivos para comunicarse con el otros programas, además es la forma más simple de almacenar información (hacer persistente los datos). Por ejemplo con el objetivo de generar informes-documentos-reportes. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 30 Leer y Guardar información en archivos Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 31 Tipos de archivos: Los archivos en ANSI C pueden contener información en formato texto (ASCII) o bien en formato binario. Esto no crea dos tipos de flujo de datos: Flujos Texto: Es una secuencia de caracteres. En un flujo de texto, pueden ocurrir ciertas conversiones de caracteres si el entorno del sistema lo requiere. El número de bytes escritos y leídos puede no ser iguales. Flujos Binarios: Es una secuencia de bytes con una correspondencia de uno a uno con los dispositivos externos. No se realizan conversiones de caracteres. El número de bytes escritos y leídos es el mismo. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 32 Descripción de archivos de texto. La función booleana feof() devuelve el valor true(1) si se ha alcanzado la marca de fin de archivo o false (0) en otro caso. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 33 Descripción de archivos binarios. La función booleana feof() devuelve el valor true(1) si se ha alcanzado la marca de fin de archivo o falkse (0) en otro caso. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 34 Sistema de Archivos en ANSI C. La librería stdio.h nos provee un conjunto de funciones: - fopen( ): abrir un archivo - fclose( ): cerrar un archivo - fputc ( ): escribe un char en archivo - fgetc ( ): lee un char de un archivo - fseek ( ): búsqueda de byte - fprintf ( ): printf para archivos - fscanf ( ): scanf para archivos - feof ( ): indentificador de final de archivo - ferror ( ): devuelve 1 o 0 si hubo error en el flujo - rewind ( ): se posiciona al inicio del archivo - remove ( ): borra un archivo Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 35 Operaciones básicas para el uso de archivos. Antes de usar un archivo se debe declarar y abrir y una vez terminado uso se debe cerrar: Declaración: Se declara con el tipo OPEN predefinido en la función stdio.h. El formato es: FILE *<nombre lógico de archivo>; Apertura: <nombre lógico de archivo> = fopen("nombre", "modo"); Obs: “nombre”: Es el nombre físico del archivo. Cerrar archivo fclose(<nombre lógico de archivo>); Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 36 Definición de los modos de uso: “Modo” es alguna de las siguientes: r : sólo lectura (read) w : escritura desde el comienzo del archivo (write) a : escritura añadida al final del archivo (append) a+ : Lectura y escritura añadida al final del archivo (append) r+ : lectura y escritura w+:escritura y lectura rb :sólo lectura (archivo binario) wb :escritura desde el comienzo del archivo (archivo binario) ab :escritura añadida al final del archivo (archivo binario) t: tipo texto, si no se especifica "t" ni "b", se asume por defecto que es "t" b: tipo binario Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 37 Ejemplo:. FILE *a, *b, *c, *d; main( ) { a=fopen("datos.txt", "r"); b=fopen("nombres.dat", "a+"); c=fopen("ipc.tex", "rt"); d=fopen("c:/cambios.rtf", "r+b"); .......... } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 38 Ejemplo:. FILE *arch; arch=fopen(“archivo.txt","r"); ...... fclose(arch); Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 39 Operaciones sobre archivos Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 40 Función de detección de fin de archivo: feof(). Pemrite detectar cuando se ha llegado al fin de archivo y por lo tanto ya no es posible seguir leyendo. Fin de Archivo: int feof(FILE *archivo); Obs: El valor de retorno es 1 cuando se ha llegado a fin de archivo, de los contrario el retorno es 0. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 41 Función para saber donde está el cursor: ftell(). Permite saber donde se encuentra ubicado el cursor. Ubicación del cursor: long int ftell(FILE *archivo); Obs: -Función para averiguar cuál es la posición actual del cursor de lectura/escritura de un archivo -El retorno será la posición o -1 si se produjo un error Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 42 Formatos de lectura y escritura: Funciones fscan() y fprintf(). Permiten leer y escribir hacia y desde un archivo de texto. Impresión: int fprintf(FILE *fp, "cadena de control", tipo arg1, tipo arg2, ...); Obs. El retorno es el número de caracteres impreso. Este es negativo si se produce un error. Lectura: int fscanf(FILE *fp, "cadena de control", &arg1, &arg2, ...); Obs: Los argumentos de fscanf() se deben pasar por referencia. Retorna el número de caracteres leídos y EOF si hay errror. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 43 Ejemplo: Funciones fprintf() y fscanf(). #include <stdio.h> #include <stdlib.h> FILE *arch; FILE *inf; int main() { int i,n1,n2,n3; arch=fopen("notas.dat","w"); for (i=0;i<3;i++) { printf("\nnotas alumno:%d",i); printf("Ingrese sus 3 notas:"); scanf("%d %d %d",&n1,&n2,&n3); fprintf(arch,"%d %d %d\r\n",n1,n2,n3); } fclose(arch); inf=fopen("notas.dat","r"); i=0; while (!feof(inf)) { fscanf(inf,"%d %d %d",&n1,&n2,&n3); if ( !feof(inf) ) { printf("\n%d %d %d",n1,n2,n3); printf("Alumno %d promedio=%d",i,(n1+n2+n3)/3); }; i++; }; system("PAUSE"); return 0; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 44 Formatos de lectura y escritura: Funciones fgetc() y fputc(). Permiten hacer lectura/ escritura de un solo caracter: Impresión: int fputc(int carácter, FILE *archivo); Obs. El valor de retorno es el carácter escrito, si la operación de escritura fue realizada, de los contrario devuelve EOF Lectura: int fgetc(FILE *archivo); Obs. -El valor de retorno es un carácter leído como un unsigned char convertido a int. -Si al leer no hay un carácter disponible el valor de retorno es EOF Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 45 Ejemplo: Funciones fgetc() y fputcf(). #include <stdio.h> #include <stdlib.h> int main() { FILE *archivo; char c; int i; archivo=fopen("datos.dat","w"); for (i=0;i<3;i++) fputc('A',archivo); fclose(archivo); archivo=fopen("datos.dat","r"); while(!feof(archivo) ) { c=fgetc(archivo); printf("%c",c); } fclose(archivo); system("PAUSE"); return 0; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 46 Formatos de lectura y escritura: Funciones fgets() y fputs(). Permiten hacer lectura/ escritura de strings: Impresión: int fputs(const char *cadena, FILE *archivo); Obs. -Función que escribe una cadena en un archivo. -La cadena es escrita sin el valor de retorno y sin el carácter de finalización de string -Parámetros: cadena a escribir, archivo -El valor de retorno es un número positivo o EOF en caso de error Lectura: char *fgets(char *cadena, int n ,FILE *archivo); Obs: - Función para lectura de string (cadena de caracteres). -Lee: n-1 caracteres o hasta que encuentra salto de línea. Cuando encuentra salto de línea, este también es leído. -Los parámetros son: la cadena a leer, número máximo de caracteres a leer y el FILE. -El valor de retorno es un puntero a la cadena leída en caso de lectura correcta, de lo contrario retorna NULL. Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 47 Ejemplo: Funciones fgets() y fputs(). #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i; char str[20]; char str1[10]; FILE *s; FILE *e; s=fopen("datos.txt","w"); for (i=0;i<5; i++) { itoa(i,str1,5); strcpy(str,"string numero:"); strcat(str, str1); fputs(str,s); }; fclose(s); e=fopen("datos.txt","r"); while (!feof(e)) { fgets(str,16,e); if (!feof(e)) printf("%s\n",str); }; fclose(e); system("PAUSE"); return 0; Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino } 48 Formatos de lectura y escritura: Funciones fread() y fwrite(). Permiten hacer lectura/ escritura de datos binarios: Impresión: size_t fwrite(void *ptr, size_t tamaño, size_T nregistros, FILE *archivo); Obs. -Función que permite escribir en un archivo uno o varios registros de una misma longitud almacenados a partir de una dirección de memoria determinada -El valor de retorno es el número de registros escritos -Parámetros: una puntero a la memoria donde se almacenarán los datos, el tamaño de cada registro, el número de registros a escribir y el archivo de donde se escribirán Lectura: size_t fread(void *ptr, size_t tamaño, size_t nregistros, FILE *archivo); Obs: -Función capaz de leer desde un archivo uno o varios registros de la misma longitud a partir de una dirección de memoria determinada -El valor de retorno es el número de registros leídos -Parámetros: un puntero a la memoria donde se almacenarán, el tamaño de cada registro, el de Archivos: Ing. Yim número de registros a leer y el Organizacion archivo de donde se lee 49 Isaias Apestegui Florentino Ejemplo: Funciones fread() y fwrite(). #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *s; FILE *e; int i; s=fopen("binario.dat","w"); for (i=1000;i<1005;i++) fwrite(&i,sizeof(i),1,s); fclose(s); e=fopen("binario.dat","r"); while (!feof(e)) { fread(&i,sizeof(i),1,e); if (!feof(e)) printf("%d\n",i); } fclose(e); system("PAUSE"); return 0; } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 50 Función de reubicación del cursor de lectura: rewind(). Permite volver a iniciar la lectura de un archivo. Reubicación de cursor: void rewind(FILE *archivo); Obs: Función rebobinar, sitúa el cursor de lectura/escritura en el primer elemento del archivo (la información que fue registrada primero que todas). . Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 51 Ejemplo: Funciones rewind(). #include <stdio.h> #include <stdlib.h> int main() { FILE *a; struct alumno { char nombre[50]; int nota; }; struct alumno curso[3]; struct alumno registro; strcpy(curso[0].nombre,"Juan Vergara"); curso[0].nota=99; strcpy(curso[1].nombre,"Victor Chavez"); curso[1].nota=55; strcpy(curso[2].nombre,"Oscar Marin"); curso[2].nota=33; a=fopen("vector.dat","w+"); fwrite(&curso,sizeof(curso[0]),1,a); fwrite(&curso[1],sizeof(curso[1]),2,a); rewind(a); while (!feof(a)) { fread(&registro,sizeof(registro),1,a) ; if (!feof(a)) { printf("%s ",registro.nombre); printf("%i\n",registro.nota); }; }; fclose(a); system("PAUSE"); return 0; Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino } 52 Función de posicionamiento del cursor: fseek(). Permite volver a iniciar la lectura de un archivo. Reubicación de cursor: int fseek(FILE *archivo, long int desp, int origen); Obs: -Función cuya utilidad es posicionar el cursor del archivo para leer o escribir en un lugar deseado -Retorna 0 en caso de éxito -Parámetros: el archivo, el desplazamiento en bytes -El parámetro origen puede ser uno de los siguientes(define 0, 1, 2) - SEEK_SET: comienzo de archivo - SEEK_CUR: ubicación actual - SEEK_END: fin de archivo Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 53 Ejemplo. int main(int argc, char *argv[]) { FILE *salida; FILE *entrada; char letra; int i; salida=fopen("archivo.txt","w"); fprintf(salida,"%s","123456789"); fclose(salida); entrada=fopen("archivo.txt","r"); printf("posicion despues de abrir:%ld\n",ftell(entrada)); for (i=0; i<5; i++ ){ fgetc(entrada); } printf("posicion despues de leer 5 caracteres: %ld\n",ftell(entrada)); fseek(entrada, 0,SEEK_END); printf("posicionarse al final: %ld\n",ftell(entrada)); fseek(entrada, 0,SEEK_SET); printf("POsicionarse al inicio: %ld\n",ftell(entrada)); fseek(entrada, 1,SEEK_SET); printf("POsicionarse 1 depues del inicio: %ld\n",ftell(entrada)); fseek(entrada, -1,SEEK_END); printf("posicionarse 1 antes del final: %ld\n",ftell(entrada)); fseek(entrada, -2,SEEK_CUR); printf("posicionarse 2 antes del actual: %ld\n",ftell(entrada)); } Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 54 Función para limpiar el buffer de lectura: fflush(). Permite posicionar el curso en una localización determinada por el numero de bytes. Limpieza del buffer: int fflush(FILE *archivo); Obs: -Esta función fuerza la salida de los datos acumulados en el buffer de salida del archivo. Para mejorar el manejo de archivos se utilizan buffers (almacenes temporales de datos en memoria) las operaciones de salida se hacen a través del buffer, y sólo cuando el buffer se llena se realiza la escritura en el disco y se vacía el buffer. En ocasiones nos hace falta vaciar ese buffer de un modo manual. -El valor de retorno es 0 en caso de éxito, y EOF en caso contrario . Organizacion de Archivos: Ing. Yim Isaias Apestegui Florentino 55