Entrada/Salida de Archivos Herman Schinca Clase 10 29 de Abril de 2011 ¿Para qué? Guardar datos y no tener que volver a correr el programa (para esa entrada) Se necesita leer los datos con otro programa (MatLab por ejemplo) Debo leer datos almacenados en un archivo Estructura Básica (incluyo <stdio.h>) Abro Archivo /* Trabajo con el Archivo */ Cierro Archivo Pero... ¿Qué es un archivo? Un conjunto de bytes guardados en disco (u otros dispositivos) que tiene nombre y ruta de acceso. En C los representamos con el tipo FILE. Trabajamos con un puntero a FILE. Abriendo el archivo FILE* miArchivo; miArchivo = fopen(dirección,modo); Dirección Indica la ruta en donde está guardado el archivo. Si está en la misma carpeta que mi código, el nombre del archivo. Sino, ruta completa (no siempre...). Ni Modo “r” - Abre archivo como Sólo lectura. El archivo debe existir. “w” - Crea un archivo para escritura (ojo con el nombre!). “a” - Escribe a partir del final del archivo. Ni Modo “r+” - Abre archivo como Lectura+Escritura. “w+” - Crea un archivo para Lectura+Escritura. “a+” - Escribe a partir del final del archivo aunque puede leer todo el archivo. Cerrando el archivo fclose (miArchivo); Ejemplo FILE* miArchivo; miArchivo = fopen("archivo1.txt", "w+"); fclose(miArchivo); Error al abrir archivo Porque... ...no existe. ...lo está usando otro programa que no admite concurrencia (¿QUÉ?). ...está protegido (por permisos, contraseña, etc.). Error al abrir archivo Debo chequear su correcta apertura: If(!miArchivo){ //Exploto } else{ //Me porto bien } Escribiendo el archivo fputc(unChar, miArchivo); Se escribe unChar en el archivo y se incrementa en 1 el puntero al archivo. MiniEjercicio Crear un archivo llamado “EstoNoEsUnArchivo” con extensión .txt y escribir el abecedario en mayúscula separando cada letra por una coma, es decir: A,B,C,...,X,Y,Z Posible Solución FILE* miArchivo; miArchivo = fopen("MiNombre.txt", "w"); char c; for(c = 'A'; c < 'Z'; c++){ fputc(c, miArchivo); fputc(',', miArchivo); } fputc(c, miArchivo); fclose(miArchivo); Escribiendo el archivo fputs(“Un string con lo que quiera”, miArchivo); El '\0' que indica el final del string no se copia. El puntero al archivo se incrementa en la longitud del string - 1. Leyendo el archivo char c; c = fgetc(miArchivo); Se lee un char del archivo, se lo retorna y se incrementa en 1 el puntero al archivo. Leyendo el archivo ¿Cómo sé si llegué al final del archivo? Carácter especial llamado EOF (sin comillas simples) nos dice que alcanzamos el final del archivo. MiniEjercicio Abrir “EstoNoEsUnArchivo.txt”, contar cuántas comas tiene e imprimir ese valor por pantalla. (Ojo con el modo en que lo abren...) (Debería dar 25 :-P) Posible Solución miArchivo = fopen("MiNombre.txt", "r"); char c = '1'; int cantComas = 0; while(c != EOF){ //ó !feof(miArchivo) c = fgetc(miArchivo); if (c == ',') cantComas++; } printf("%d", cantComas); fclose(miArchivo); Leyendo el archivo fgets(miString, N, miArchivo); Lee N-1 caracteres de miArchivo o hasta que encuentre un '\n' o un EOF (lo que ocurra primero), los guarda en miString y le pone un '\0'. Si lee un '\n' también lo guarda en miString. Leer y escribir con formato fscanf(miArchivo, “formato”, param1,...,paramN); fprintf(miArchivo, “formato”, param1,...,paramN); Ejemplo char nombre[31] = "Filisberto Aristóbulo Brendarj"; int edad = 75; float altura = 1.01; fprintf(miArchivo, "Nombre: %s\nEdad: %d\nAltura: %f", nombre, edad, altura); ¿Qué formato uso? Y si queremos leer los datos del ejemplo anterior, ¿cómo harían? ¿Elegimos el mejor formato? ¿En función de qué? ¿Hay otros? ¿Infinitos? ¿Cómo lo demostraría? Formato útil para Arreglos cantidadDeElementos elemento1 elemento2 … elementoN (donde N=cantidadDeElementos) En código int arr[11] = {0,2,4,6,8,10,11,13,15,17,19}; fprintf(miArchivo, "%d\n",11); int i; for(i=0;i<11;i++){ fprintf(miArchivo, "%d ",arr[i]); } Formato útil para muchos Arreglos CantidadDeArreglos tamArreglo1 elemento1 elemento2 … elementoN tamArreglo2 elemento1 elemento2 … elementoM … tamArregloK elemento1 elemento2 … elementoP Formato útil para Matrices cantidadDeFilas cantidadDeColumnas elemento11 elemento12 … elemento1M elemento21 elemento22 … elemento2M … elementoN1 elementoN2 … elementoNM (donde N=cantidadDeFilas y M=cantidadDeColumnas) Anticipo Memoria Dinámica Pero, ¿cómo hacemos para cargar un arreglo o una matriz cuya dimensión no conocemos desde un archivo? ¡Necesitamos usar Memoria Dinámica! No se lo pierda, ¡próximamente en IC 2011! Rebobinando un poco... Para volver al inicio del archivo, es decir, posicionar miArchivo nuevamente al comienzo: rewind(miArchivo) Me paro donde quiero fseek(miArchivo, N, origin) Donde N es la cantidad de bytes que me quiero mover y origin indica desde donde sumo N. Origin puede ser: • SEEK_SET: desde el principio. • SEEK_CUR: desde donde estoy. • SEEK_END: desde el final del archivo. Ejemplo fputs("Esta frase no tiene sentido.", miArchivo); fseek(miArchivo,11,SEEK_SET); fputs("sí",miArchivo); Referencias Para C: http://www.cplusplus.com/reference/clibrary/cstdio/ Para el que quiera mirar en Python: http://docs.python.org/tutorial/inputoutput.html#rea ding-and-writing-files Eso es todo ¿¿¿Preguntirijillas???