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

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

Например:

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

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

Ответы

Ответ 1

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

Ответ 2

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

Ответ 3

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

Ответ 4

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