Фортран неформатированный формат файла
Я не понимаю формат неформатированных файлов в фортране.
Например:
open (3,file=filename,form="unformatted",access="sequential")
write(3) matrix(i,:)
выводит столбец матрицы в файл. Я обнаружил, что он дополняет файл 4-мя байтами на обоих концах, однако я не совсем понимаю, почему или как контролировать это поведение. Есть ли способ убрать обивку?
Спасибо
4 ответа
Для неформатированного ввода-вывода компиляторы Fortran обычно записывают длину записи в начале и конце записи. Большинство, но не все компиляторы используют четыре байта. Это помогает в чтении записей, например, длина в конце помогает с операцией возврата. Вы можете подавить это с помощью нового режима потокового ввода-вывода Fortran 2003, который был добавлен для совместимости с другими языками. Используйте access='stream' в вашем открытом заявлении.
По этой причине я никогда не использовал последовательный доступ с неформатированным выводом. Однако это зависит от приложения, и иногда удобно иметь индикатор длины записи (особенно для неструктурированных данных). Как предложил steabert в " Просмотр двоичного вывода от fortran на gnuplot", вы можете избежать этого с помощью ключевого аргумента ACCESS = 'DIRECT'
, в этом случае вам нужно указать длину записи. Этот метод удобен для эффективного хранения больших многомерных структурированных данных (постоянная длина записи). В следующем примере записывается неотформатированный файл, размер которого равен размеру массива:
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
Обратите внимание, что это не идеальный подход в смысле переносимости. В неотформатированном файле, написанном с прямым доступом, нет информации о размере каждого элемента. Текстовый файл readme, в котором описывается размер данных, отлично справляется со мной, и я предпочитаю этот метод вместо заполнения в последовательном режиме.
Fortran IO основан на записях, а не на потоках. Каждый раз, когда вы пишете что-то через write()
вы не только пишете данные, но также начинаете и заканчиваете маркеры для этой записи. Оба маркера записи имеют размер этой записи. По этой причине запись группы реалов за одну запись (одна запись: один маркер начала, группа реалов, один маркер конца) имеет разный размер по сравнению с записью каждого реального в отдельной записи (несколько записей, каждая одного маркера начала, одного действительного и одного маркера конца). Это очень важно, если вы записываете большие матрицы, так как вы можете раздувать занятие, если неправильно написали.
Fortran Unformatted IO. Я хорошо знаком с различными выходами, использующими компиляторы Intel и Gnu. К счастью, мой огромный опыт 1970-х годов позволил мне расшифровать вещи. Gnu дополняет записи 4-байтовыми целочисленными счетчиками, дающими длину записи. Intel использует 1-байтовый счетчик и несколько встроенных значений кодирования для обозначения продолжения записи или окончания подсчета. Можно по-прежнему иметь очень большую длину записи, даже если используется только 1 байт. У меня есть программное обеспечение, скомпилированное компилятором Gnu, которое мне пришлось изменить, чтобы он мог читать неформатированный файл, сгенерированный любым компилятором, поэтому он должен определить, какой формат он находит. Чтение неформатированного файла, сгенерированного компилятором Intel (который следует за "старыми" днями IBM), занимает "навсегда" с помощью fgetc Gnu или открытия файла в потоковом режиме. Преобразование файла в то, что ожидает Gnu, приводит к увеличению до 100 раз. быстрее. Это зависит от размера вашего файла, если вы хотите беспокоиться об обнаружении и преобразовании или нет. Я сократил время запуска моей программы (которое открывает большой неотформатированный файл) с 5 минут до 10 секунд. Мне пришлось добавить параметры для повторного преобразования еще раз, если пользователь захочет вернуть файл обратно в скомпилированную программу Intel.Это все боль, но все готово.