Неожиданное заполнение в неформатированном файле Fortran

Я не понимаю формат неформатированных файлов в Фортране.

Например:

open (3,file=filename,form="unformatted",access="sequential")
write(3) matrix(i,:)

выводит столбец матрицы в файл. Я обнаружил, что он дополняет файл 4 байтами с обеих сторон, однако я действительно не понимаю, почему и как контролировать это поведение. Есть ли способ убрать накладку?


person Andrew Spott    schedule 05.01.2012    source источник
comment
Изменил название, потому что мне очень не нравится вводящее в заблуждение использование этого термина - бинарный. Двоичный означает основание 2, которое не связано напрямую с вашей проблемой. Практически все на вашем компьютере на каком-то уровне является двоичным. В настоящее время это распространенный термин, но неформатированный в Фортране намного ближе.   -  person Rook    schedule 07.01.2012
comment
Немного полезной информации о потоке... star.le.ac.uk/ ~cgp/streamIO.html   -  person Rook    schedule 07.01.2012
comment
это похоже на дубликат stackoverflow.com/questions/8751154/, не могли бы вы не публиковать свой вопрос несколько раз?   -  person steabert    schedule 11.01.2012


Ответы (4)


Для неформатированного ввода-вывода компиляторы Фортрана обычно записывают длину записи в начале и в конце записи. Большинство, но не все компиляторы используют четыре байта. Это помогает при чтении записей, например, длина в конце помогает с операцией возврата. Вы можете подавить это с помощью нового режима Stream IO в Fortran 2003, который был добавлен для совместимости с другими языками. Используйте access='stream' в своем открытом заявлении.

person M. S. B.    schedule 05.01.2012
comment
Небольшое замечание: некоторые компиляторы, такие как Gfortran и Intel Fortran, поддерживают записи размером более 2 ГБ, несмотря на наличие 4-байтовых маркеров записей, с помощью подзаписей. - person janneb; 06.01.2012

Именно по этой причине я никогда не использовал последовательный доступ с неформатированным выводом. Однако это зависит от приложения, и иногда бывает удобно иметь индикатор длины записи (особенно для неструктурированных данных). Как было предложено 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, в котором описывается размер данных, отлично подходит для меня, и я предпочитаю этот метод вместо заполнения в последовательном режиме.

person milancurcic    schedule 11.01.2012

Fortran IO основан на записи, а не на потоке. Каждый раз, когда вы что-то записываете через write(), вы записываете не только данные, но также начальные и конечные маркеры для этой записи. Оба маркера записи соответствуют размеру этой записи. По этой причине запись группы вещественных чисел в одной записи (одна запись: один маркер начала, группа вещественных чисел, один маркер конца) имеет другой размер по сравнению с записью каждого действительного числа в отдельной записи (несколько записей, каждая из одного начального маркера, одного реального и одного конечного маркера). Это чрезвычайно важно, если вы записываете большие матрицы, так как вы можете раздуть занятие, если запишете его неправильно.

person Stefano Borini    schedule 07.01.2012
comment
то, что вы говорите, верно только для «последовательного» доступа - person steabert; 11.01.2012
comment
@steabert: который используется чаще всего (99,999%). - person Stefano Borini; 12.01.2012
comment
Примерно половина моего кода использует «прямой» доступ — так что для меня это составляет только 50%: P - person mgilson; 02.03.2013

Fortran Unformatted IO Я хорошо знаком с разными выводами с использованием компиляторов Intel и Gnu. К счастью, мой обширный опыт работы с IBM 1970-х годов позволял мне расшифровывать вещи. Gnu дополняет записи 4-байтовыми целочисленными счетчиками, указывающими длину записи. Intel использует 1-байтовый счетчик и ряд встроенных кодовых значений, чтобы обозначить запись продолжения или конец подсчета. Можно по-прежнему иметь очень длинные записи, даже если используется только 1 байт. У меня есть программное обеспечение, скомпилированное компилятором Gnu, которое мне пришлось изменить, чтобы оно могло читать неформатированный файл, сгенерированный любым компилятором, поэтому оно должно определять, какой формат он находит. Чтение неформатированного файла, сгенерированного компилятором Intel (который следует за «старыми» днями IBM), занимает «вечность» с использованием fgetc Gnu или открытием файла в потоковом режиме Преобразование файла в то, что ожидает Gnu, приводит к коэффициенту до 100 раз быстрее. Это зависит от размера вашего файла, хотите ли вы возиться с обнаружением и преобразованием или нет. Я сократил время запуска моей программы (которая открывает большой неформатированный файл) с 5 минут до 10 секунд. Мне пришлось добавить параметры для повторного преобразования обратно, если пользователь хочет вернуть файл обратно в программу, скомпилированную Intel.Это все боль, но вот и все.

person William Jacobs    schedule 16.03.2016