txt - Formato de archivo sin formato Fortran
txt fortran (4)
No entiendo el formato de los archivos sin formato en Fortran.
Por ejemplo:
open (3,file=filename,form="unformatted",access="sequential")
write(3) matrix(i,:)
genera una columna de una matriz en un archivo. Descubrí que rellena el archivo con 4 bytes en cada extremo, sin embargo, no entiendo por qué ni cómo controlar este comportamiento. ¿Hay alguna manera de quitar el relleno?
Gracias
Fortran IO se basa en registros, no en transmisiones. Cada vez que escribe algo a través de write()
, no solo está escribiendo los datos, sino también los marcadores de inicio y fin de ese registro. Ambos marcadores de registro son del tamaño de ese registro. Esta es la razón por la que escribir un grupo de reales en una sola escritura (un registro: un marcador de inicio, el grupo de reales, un marcador de extremo) tiene un tamaño diferente con respecto a escribir cada uno real en una escritura separada (varios registros, cada uno de un marcador de inicio, un marcador real y uno de final). Esto es extremadamente importante si está escribiendo matrices grandes, ya que podría aumentar la ocupación si se escribe incorrectamente.
Fortran Unformatted IO Estoy bastante familiarizado con las diferentes salidas que utilizan los compiladores Intel y Gnu. Afortunadamente, mi vasta experiencia que se remonta a la IBM de la década de 1970 me permitió descifrar cosas. Gnu rellena registros con contadores de enteros de 4 bytes que dan la longitud del registro. Intel usa un contador de 1 byte y una serie de valores de codificación incorporados para indicar un registro de continuación o el final de un conteo. Uno puede tener una longitud de registro muy larga, aunque solo se use 1 byte. Tengo un software compilado por el compilador Gnu que tuve que modificar para que pueda leer un archivo sin formato generado por cualquiera de los dos compiladores, así que tiene que detectar qué formato encuentra. Leer un archivo sin formato generado por el compilador de Intel (que sigue a los "viejos ''días de IBM) toma" para siempre "usando fgetc de Gnu o abriendo el archivo en modo continuo. Convertir el archivo a lo que Gnu espera resulta en un factor de hasta 100 veces Más rápido. Depende de su tamaño de archivo si quiere molestarse con la detección y la conversión o no. Reduje el tiempo de inicio de mi programa (que abre un archivo grande sin formato) de 5 minutos a 10 segundos. Tuve que agregar opciones para reconvertir de nuevo, si el usuario desea devolver el archivo a un programa compilado por Intel. Es todo un dolor, pero ya está.
Nunca usé el acceso secuencial con salida sin formato por esta razón exacta. Sin embargo, depende de la aplicación y, a veces, es conveniente tener un indicador de longitud de registro (especialmente para datos no estructurados). Como lo sugiere steabert en Mirando la salida binaria de fortran en gnuplot , puede evitar esto usando el argumento de palabra clave ACCESS = ''DIRECT''
, en cuyo caso debe especificar la longitud del registro. Este método es conveniente para el almacenamiento eficiente de grandes datos estructurados multidimensionales (longitud de registro constante). El siguiente ejemplo escribe un archivo sin formato cuyo tamaño es igual al tamaño de la matriz:
REAL(KIND=4),DIMENSION(10) :: a = 3.141
INTEGER :: reclen
INQUIRE(iolength=reclen)a
OPEN(UNIT=10,FILE=''direct.out'',FORM=''UNFORMATTED'',&
ACCESS=''DIRECT'',RECL=reclen)
WRITE(UNIT=10,REC=1)a
CLOSE(UNIT=10)
END
Tenga en cuenta que este no es el enfoque ideal en el sentido de portabilidad. En un archivo sin formato escrito con acceso directo, no hay información sobre el tamaño de cada elemento. Un archivo de texto readme que describe el tamaño de los datos hace el trabajo bien para mí, y prefiero este método en lugar del relleno en modo secuencial.
Para las IO no formadas, los compiladores de Fortran suelen escribir la longitud del registro al principio y al final del registro. La mayoría pero no todos los compiladores usan cuatro bytes. Esto ayuda a leer registros, por ejemplo, la longitud al final ayuda con una operación de retroceso. Puede suprimir esto con el nuevo modo Stream IO de Fortran 2003, que se agregó por compatibilidad con otros idiomas. Use access = ''stream'' en su declaración abierta.