Написание больших двоичных файлов на Фортране с доступом = поток - PullRequest
0 голосов
/ 04 мая 2018

У меня возникли проблемы с пониманием форматирования бинарных файлов, которые я пишу с помощью Fortran. Я использую следующую подпрограмму для записи двоичных файлов на диск:

SUBROUTINE write_field(d,m,outfile)

    IMPLICIT NONE    
    REAL, INTENT(IN) :: d(m,m,m)
    INTEGER, INTENT(IN) :: m
    CHARACTER(len=256), INTENT(IN) :: outfile

    OPEN(7,file=outfile,form='unformatted',access='stream')
    WRITE(7) d
    CLOSE(7)

END SUBROUTINE write_field

Насколько я понимаю, опция access=stream заключалась в том, что это исключило бы стандартный верхний и нижний колонтитулы, которые поставляются с двоичным файлом Fortran (см. Неформатированный формат файла Fortran ).

Если я напишу файл с m=512, то я ожидаю, что файл должен быть 4 x 512^3 bytes = 536870912 bytes ~ 513 Mb, но на самом деле они на 8 байт длиннее, и приходят в 536870920 bytes. Я предполагаю, что эти дополнительные байты - это 4-байтовые заголовки и нижние колонтитулы, которые я хотел подавить с помощью access='stream'.

Ситуация меня сбивает с толку, если я напишу файл с m=1024, тогда я ожидаю, что файл должен быть 4 x 1024^3 bytes = 4294967296 ~ 4.1 Gb, но на самом деле они на 24 (!) Байта длиннее этого, входя в 4294967320 bytes , Я не понимаю, почему здесь 24 дополнительных байта, которые, по-видимому, соответствуют 6 (!) Верхним или нижним колонтитулам.

Мои вопросы:

(а) Можно ли заставить Фортран написать двоичный файл без колонтитулов?

(b) Если ответ (а) - «нет», могу ли я убедиться, что больший двоичный файл имеет ту же структуру заголовка и нижнего колонтитула, что и меньший двоичный файл?

(c) Если ответы на (a) и (b) оба «нет», то как я могу понять, где эти дополнительные верхние и нижние колонтитулы находятся в файле.

Я использую ifort (версия 14.0.2) и записываю двоичные файлы в небольшой кластер Linux.

ОБНОВЛЕНИЕ: при запуске одного и того же кода с OSx и скомпилированным с gfortran 7.3.0 бинарные файлы получаются с ожидаемыми размерами, как и всегда 4 x m^3 bytes, даже когда m=1024. Так что, похоже, эта проблема связана со старым компилятором.

ОБНОВЛЕНИЕ: На самом деле проблема возникает только при использовании ifort 14.0.2 Я обновил текст, чтобы отразить это.

1 Ответ

0 голосов
/ 29 мая 2018

Эта проблема решается добавлением status='replace' в команду Fortran open. не связано с компилятором.

При access='stream' и без status='replace' старый двоичный файл не заменяется автоматически новым двоичным файлом и просто перезаписывается до определенной точки (https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/676047).. В результате старый двоичный файл просто имеет Байты заменены до размера нового двоичного файла, оставляя при этом любые дополнительные байты и размер файла без изменений. Это проблема, если новый размер файла меньше старого размера файла. Проблему трудно диагностировать, так как время штамп на файле обновлен , поэтому файл выглядит как новый при запросе ls -l.

Минимальный рабочий пример, воссоздающий эту проблему:

PROGRAM write_binary_test_minimal

    IMPLICIT NONE
    REAL :: a

    a=1.

    OPEN(7,file='test',form='unformatted')
    WRITE(7) a
    CLOSE(7)

    OPEN(7,file='test',form='unformatted',access='stream')
    WRITE(7) a
    CLOSE(7)

END PROGRAM write_binary_test_minimal

Первый write генерирует файл 'test' размером 8 + 4 = 12 байтов. Где 8 - это стандартный Fortran-двоичный заголовок и нижний колонтитул, а 4 - размер в байтах a. Во втором операторе write, даже если было установлено access='stream', только первые 4 байтов ранее сгенерированного 'теста' перезаписываются, оставляя файл размером 12 байтов! Решением этой проблемы является изменение второго оператора записи на

OPEN(7,file='test',form='unformatted',access='stream',status='replace')

с явным status='replace' для обеспечения замены старого файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...