Fundamentos de Informática Tema 8 Ficheros y Formatos 1 INTRODUCCIÓN MANEJO DE FICHEROS (De Datos) Son importantes porque permiten: - Almacenar datos - Probar programas sin introducir cada vez los datos. Se guardan con otra extensión (.Dat, .Txt, ) Se crean con programa F90, o editor. Fin de datos: Marca EOF Cada línea del fichero es un registro Sentencia OPEN. Abre fichero (unidad conexión a disco) y asigna atributos OPEN (Unit = u, File = ’nombre’, IOStat=S1, Status= ’est’, Acces=’frm’, Action=’acc’, Position=’pos’, Blank=’bla’) 2 MANEJO DE FICHEROS Especificaciones (en negrita la opción por defecto) OPEN (Unit = u, File = ’nombre’, IOStat=S1, Status= ’est’, Acces=’frm’, Action=’acc’, Position=’pos’, Blank=’bla’) OPEN (11, File = ‘Pepe.Dat’) es la forma más habitual de usarlo. (UNIT = u). Asocia unidad o canal u (de 1 a 99) al fichero, y lo identifica. (FILE = ’nombre’). Asocia la unidad u con el nombre del fichero. (IOStat = S1). S1 = 0, si no hay errores al abrir el fichero. (Acces = ’frm’). ’direct’ acceso directo (aleatorio), o ’sequential’ (Status = ’est’).: ’old’ el fichero existe (o error); ’new’ crea nuevo (si existe, error); ’replace’ (lo borra ) y lo crea; ’unknown’ lo usa o lo crea. (Action = ’acc’). ’read’, ’write’, ’readwrite’ (por defecto) (Position = ’pos’). ’rewind’ puntero al principio; ’append’ antes EOF (BLANK = ’bla’). ’zero’ los blancos como 0; ’null’ blancos como tales. 3 MANEJO DE FICHEROS SENTENCIAS de CIERRE Y POSICIONAMIENTO Unit se puede omitir u es el primer argumento Si se omite File= ‘nom’, se crea un fichero temporal (scracht) CLOSE (u, Iostat=S1, Status=’est’). - u y S1 como en OPEN; est = Keep o Delete (el fichero cerrado) - Al acabar la ejecución, todo fichero se cierra automáticamente. REWIND (u, Iostat=S1). Rebobina el fichero en la unidad u, o sea, lleva el puntero de posición e/s, al inicio del fichero. BACKSPACE (u, Iostat=S1). El puntero e/s retrocede un registro en el fichero . ENDFILE (u, Iostat=S1). Pone marca de (EOF), en la posición actual del puntero, en el fichero unidad u. 4 SENTENCIAS GENERALES DE ENTRADA Y SALIDA F90 trata a la impresora y la pantalla como un fichero READ (Unit =I, Format=J, Iostat = S1, Advance = ’av’, Size = t ) Lista variables WRITE (I, J, Iostat = S1, Advance = ’av’) Lista argumentos Cada Read/Write implica una nueva línea de lectura/impresión. I (entero) indica unidad (prefijada con sentencia OPEN: unit). (*) E/S por defecto J (entero) indica etiqueta de una Sententencia FORMAT. (*) formato por defecto. IOSTAT = S1. S1 = 0 si se detecta el final del fichero. ADVANCE = ’av’. Indica avance del puntero E/S. ’yes’ pone el puntero al inicio de la línea siguiente. ’no’ el puntero no se mueve (Lee/Imprime en la misma línea). SIZE = t. (READ), Advance = ’No’ t almacena numero de caracteres leídos. Al usar entrada/salida (E/S) por defecto, se simplifica: READ j , ; WRITE ‘(formato)’, (E por defecto se puede omitir) (READ (*,*) READ*, // WRITE (*,*) PRINT*, 5 EJEMPLO : Guardar una lista de ciudades y temperaturas en un fichero .f90 6 PROGRAM Temperaturas Character (15), Dimension(20):: Ciudad ; Integer:: I, J REAL, Dimension(20):: Temp DO I = 1,20 WRITE(*,*) 'Escribe Ciudad y Temperatura' Read *, Ciudad(I), Temp(I) EndDo OPEN (10, FILE= 'Ciudades.Tem') Do I = 1, 20 WRITE(10, *) Ciudad(I), TEMP(I) EndDo Rewind (10); I = 1 Do While (.not.eof(10)) Read(10,*) ciudad (I) ; I = I + 1 EndDo Print*, ‘La ciudad 5 en el fichero es ‘, ciudad(5) END PROGRAM Temperaturas FORMATOS de E/S: La sentencia FORMAT. Descriptores etq FORMAT (lista especificaciones) etq: etiqueta de la sentencia FORMAT referida en una E/S. READ (*, 20) X,Y 20 FORMAT (F10.5, F5.1) - Las especificaciones separadas por comas (,). - Cada una referida a una variable (E), argumento (S), salto (espacios, líneas, ..) - COMPLEX necesitan dos especificaciones. - Se forman con Descriptores de Formato para cada tipo de dato. DESCRIPTORES NUMÉRICOS. (justificación a la derecha) I: Enteros, Iw (Iw.v ; v < w): v (num mínimo dígitos) ; w (anchura total) -148 tiene el formato I4 ; 3478 formato I5 ; (@-00145 I7.5 ,@ blanco F: Real sin exponente, Fw.d ; E:con exponente, Ew.d (Ew.dEe) (d decimales) -37.8 tiene el Formato F5.1 ; 0.038E-17 formato E10.3. 0.123E-0111 tiene el formato E12.3E4 7 DESCRIPTOR ALFABÉTICO. (justificación a la izquierda) A: Cadenas, Aw . [w] es la longitud de la cadena. Al leer con este Formato, no es necesario poner la cadena entre comillas. Los valores literales cadenas se pueden poner entre ’ ’ en sentencias FORMAT: 10 FORMAT (5X, ’Hoy es el’, I2, ’ de octubre de 19’, I2) 15 FORMAT (10X, 60(’*’)). !! 60(‘*’) repite el * 60 veces. DESCRIPTORES DE POSICIÓN. X : Saltar espacios, nX (salta n espacios) WRITE (6, 20) I, J, K, L 20 FORMAT (1X, I2, 9X, I2, 5X, I2, F5.4) / : Salta a columna 1 de línea siguiente (no se separa con , de los otros) 20 FORMAT (1X, I2 / 2X, I3 //// I2, F5.4). T(Tabulador): Tn lleva a columna n. TRn (TLn) salta n posiciones a drcha (izqda) 20 FORMAT(1X, I2, T9, I2, TR15, I2, TL10, F7.2) Repetición. Salvo / y T, un número delante del descriptor . 3I5 es como I5, I5, I5 ; 3(I2, 5X, F6.2) repite 3 veces la secuencia. 8 ALGUNAS INDICACIONES TÉCNICAS Formato Directo en la sentencia E/S. Podemos sustituir el * (READ *, PRINT *), por un número de etiqueta de FORMAT, e incluso por descriptores de formato, pero colocándolos entre comillas: ’( Lista descriptores )’. READ 100, PRINT 50, READ ’(1X, I2, A8)’, PRINT ’(1X, F8.2 / 7X, I8)’ CARACTERES DE CONTROL DE IMPRESIÓN FORTRAN usa el carácter que se va a escribir en la primera columna, para el control vertical de la impresión (sin imprimirlo): [Espacio:] Pasa a la línea siguiente y escribe. [0] Salta 2 líneas e imprime (doble espaciado). [1] Salta a la página siguiente. [+] No avanza línea. Permite sobreimpresión. Es importante no escribir nada en la columna 1. FORMAT debe empezar con (1X, ) 9 NO HAY SUFICIENTES FORMATOS Si no hay suficientes especificaciones para todos los elementos de E/S, se busca en la sentencia FORMAT, de derecha a izquierda, el primer paréntesis abierto, y se repiten todas las especificaciones desde aquí hasta el final del formato, las veces que haga falta. OTROS DESCRIPTORES Hay otros descriptores que no usaremos aquí. Además, algunos compiladores pueden añadir otros. • SP, SS y S para controlar el signo + en los números positivos. • G y D para números reales y Doble Precisión respectivamente. • ENw.d(Ee) y ESw.d(Ee) variantes para reales forma científica. • BN y BZ se usan para controlar si los blancos son tales o ceros. • L para datos de tipo lógico • : permite terminar un formato, si no hay más datos para E / S . 10 PROGRAM Temperaturas !Nom ciudad hasta 15 caracteres. CHARACTER (15), Dimension(20):: Ciudad; Character(12):: Cad INTEGER:: I, J ; REAL, Dimension(20):: Temp DO I = 1, 20 !! Para Probar el programa poner 4 ciudades write(*,*) 'escribe ciudad y temperatura ' ; read (*,16) ciudad(i), temp(i) EndDo.f90 OPEN (10, FILE= 'Ciudades.Tem') Print *, ' Num CIUDAD TEMPERATURA OBSERVACIONES‘ ; Print ‘(50’=‘)’, Do 20 I = 1, 20 Programa F-90, que lee del teclado, temperaCad = ' ' turas y nombres de 20 ciudades, y escribe en IF (Temp .GT. 30.0) THEN una tabla, con encabezamiento subrayado. CAD = 'Mucho CALOR' Indica, ’Mucho CALOR’ si temp > 30 grados, y ELSEIF (TEMP(I) .LT. 5.0) THEN ’FRIO’, si es < 6 grados. Se guardan datos en Cad = 'FRIO' registros del fichero Ciudades.Tem ENDIF Write(*,17) I, Ciudad(I), Temp(I), Cad ; Write(10, 18) Ciudad(I), Temp(I) EndDo 16 FORMAT (A15, F6.1) ; 17 FORMAT (2X, I2, 5X, A15, 3X, F6.1, 5X, A12) 18 FORMAT (4X, A15, 10X, F6.1) END PROGRAM TEMPERATURAS 11 !! El programa, usa un fichero para guardar nombre y notas de 5 asignaturas de varios alumnos, usando un tipo dato registro (TYPE). program fiche04 implicit none character, parameter:: ch="'“ !! Ahora defino el tipo de dato NOTAS (Registro) type notas character (25):: nom ; real, dimension(3):: cali end type notas !! Ahora defino dos variables (ALUM y ALUM1) del tipo Matriz de NOTAS type (notas), dimension (100):: alum, alum1 ; character(8), dimension (3):: asig ; integer:: i, j=1 data (asig(i), i=1,3) /'mates', 'fisica','quimica'/ !! Se abre el fichero notasalo.dat y los nuevos datos se añaden al final. f90 open (5, file= .'prac811.dat', access= 'APPEND') print*, 'Introduce el nombre del alumno', j, ' (*** para finalizar)‘ ; read*, alum(j)%nom Do while (alum(j)%nom(1:3) /='***') Do I=1, 3 print*, 'Introduce la nota de ', trim(alum(j)%nom), ' en la asignatura ', asig (i) ; Read*, alum(j)%cali(i) EndDo !! Leidos todos los datos del alumno j, se escriben en el fichero (Sin Formato). Para que no haya error, se imprimen tambien !! las comillas (ch="'") y asi al leer, se lee la cadena completa porque esta entre comillas. Usando formato esto no hace falta. write (5, *) ch,alum(j)%nom,ch, (alum(j)%cali(i),i=1,3) !! Fijarse en que no se utiliza PRINT !! Ahora se imprimen los datos del alumno j en la pantalla, con DO IMPLICITO print*, alum(j)%nom, (alum(j)%cali(i), i=1,3) ; j = j+1 print*, 'Introduce el nombre del alumno', j, '(*** para finalizar)' ; read*, alum(j)%nom EndDo !! se "Rebobina" el fichero, para poner el puntero de lectura al principio rewind(5) ; j=1 !! EOF(5)= End Of File (5). Es decir, Mientras no lleguemos al Final del Fichero... !! close (5) ; open (5, file= 'notasalo.dat', blank = 'null') Do while (.not.eof(5)) !! Se leen los datos en otra Matriz de NOTAS read(5, *) alum1(j)%nom, (alum1(j)%cali(i),i=1,3) ; j=j+1 EndDo !! Ahora se imprimen, los datos que tenia antes el fichero y los que se han introducido en esta ejecución del programa. Como !! no se utiliza formato, el programa hubiera dado error de lectura con nombres de mas de una palabra, sino hubiesemos !! almacenado tambien las comillas (ch) print*, alum1(1:j-1) END 12 REVISAR Y PREGUNTAR DUDAS Este es como el anterior, pero con FORMATOS PROGRAM fiche04 de E/S. Se puede apreciar al ejecutarlo, la type notas presentación adecuada de la salida character (40):: nom ; real, dimension(5):: cali end type notas type (notas), dimension (100):: alum ; character(8), dimension (5):: asig ; integer:: i, j =1 data (asig(i), i =1,5) /'mates', 'fisica','informat', 'arte', 'quimica'/ .f90‘NOTAS.dat', access= 'APPEND') open (5, file= print*, 'Introduce el nombre del alumno', j, ' (*** para finalizar)‘ ; read*, alum(j)%nom Do while (alum(j)%nom(1:3) /='***') Do I=1, 5 print*, 'Introduce la nota de ', trim(alum(j)%nom), ' en la asignatura ', asig (i) Read*, alum(j)%cali(i) EndDo write (5, 10) alum(j:j) ; print*, alum(j)%nom, (alum(j)%cali(i), i=1,5) ; j = j+1 print*, 'Introduce el nombre del alumno', j, '(*** para fin)‘ ; read*, alum(j)%nom EndDo rewind(5) ; j=1 Do while (.not.eof(5)) read(5, 10) alum(j)%nom, (alum(j)%cali(i), i=1,5) ; j=j+1 EndDo Print*, ' ALUMNO NOTAS: MAT FIS INF ART QUI‘ ; Print 12, Print1310, alum(1:j-1) ; 10 Format (1X, A40, 5F6.2) ; 12 Format (1X, 71('=') ) END FICHERO DE DATOS NOTAS.DAT Perez López, Luis Requena Ramos, Ignacio .f90 Pérez Pereda, Pedro Felipe Uno Juan Fernández Pedro Luis Fedro Faly YoyTu Felipez de la Felipera, Felipe 14 5.40 4.30 7.80 9.00 9.50 10.00 10.00 10.00 10.00 10.00 5.00 7.00 4.00 8.00 9.00 4.00 4.00 4.00 5.00 5.00 3.00 3.00 5.40 8.00 9.20 5.00 7.00 8.00 9.00 2.00 5.00 5.00 5.00 5.00 5.00 2.00 8.00 9.00 9.70 10.00 5.00 7.00 9.70 9.80 9.90 3.00 3.00 3.00 3.00 3.00 5.67 7.69 9.12 3.46 10.01