Содержимое неформатированного двоичного файла f77

#fortran

#c #fortran #fortran77

Вопрос:

У меня есть неформатированный двоичный файл f77. Я знаю, что файл содержит 2 числа с плавающей запятой и длинное целое число, а также данные. Размер файла составляет 536870940 байт, который должен включать 512 ^ 3 значения данных с плавающей запятой вместе с 2 числами с плавающей запятой и длинным целым числом. Значения данных с плавающей запятой 512 ^ 3 составляют 536870912 байт, оставляя еще 28 байт.

Моя проблема в том, что мне нужно определить, где начинаются 28 байтов и как пропустить этот объем памяти, чтобы я мог напрямую обращаться к данным.

Я предпочитаю использовать C для доступа к файлу.

Комментарии:

1. Если f77 для Fortran, то я действительно не понимаю, почему он помечен C. Последнее предложение не оправдывает его.

2. Двоичный файл представляет собой неформатированный двоичный файл fortran. Я получаю доступ к данным на C, а не на fortran.

3. Fortran не определяет формат так называемых «неформатированных» файлов. Существует несколько распространенных вариантов, но вам нужно знать, какая реализация Fortran написала его, возможно, с какими опциями, или же выполнить некоторую судебную экспертизу. Также может иметь значение, какая конкретная последовательность операторов вывода использовалась для записи содержимого.

4. Однажды, несколько десятилетий назад, у меня была похожая проблема — чтение неформатированного двоичного файла Fortran в программу на C. После нескольких дней ударов головой о стену я, наконец, закончил писать процедуру ввода на Fortran и вызывать ее из C. У вас нет документации, чтобы сообщить вам, где появляется рассматриваемая последовательность? Вы знаете, что это либо в начале, либо в конце (а не где-то посередине)?

5. По этому поводу уже есть много вопросов и ответов.

Ответ №1:

К сожалению, не существует стандарта, что unformatted означает. Но некоторые методы более распространены, чем другие.

Во многих версиях Fortran, которые я использовал, каждая write команда записывает заголовок (часто unsigned int 32) с указанием количества байтов данных, затем данные, а затем повторяет значение заголовка на случай, если вы читаете сзади.

Из предоставленных вами значений может получиться что-то вроде этого:

  • uint32(заголовок record1), вероятно, 12.
  • float32, float32, int32 (три «других значения», о которых вы говорили)
  • uint32 (заголовок record1, такой же, как первое значение)
  • uint32 (заголовок record2, вероятно, 512 ^ 3 * 4)
  • float32*512 ^3
  • uint32 (заголовок record2, такой же, как и раньше)

Возможно, вам придется проверить порядковый номер.

Поэтому я предлагаю вам открыть файл в программе hexdump и проверить, идентичны ли байты 0-3 байтам 16-19 и повторяются ли байты 20-23 в конце данных снова.

Если это так, я попытаюсь проверить порядковый номер, чтобы увидеть, являются ли значения маленьким или большим порядковым номером, и, если повезет, у вас будут ваши данные.

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

Обновить:

В своем комментарии вы пишете, что ваши данные начинаются примерно с этого:

 0C 00 00 00 XX XX XX XX XX XX XX XX XX XX XX XX 0C 00 00 00
^- header-^                                     ^-header -^
E8 09 FF 1F (many, many values) E8 09 FF 1F
^- header-^ ^--- your data ---^ ^-header -^
 

Теперь я не знаю, как читать данные в C. Я оставляю это на ваше усмотрение. Что вам нужно сделать, это пропустить первые 24 байта, затем прочитать данные как (возможно, с небольшим порядковым номером) 4-байтовые значения с плавающей запятой. У вас останется 4 байта, которые вам больше не нужны.

Важное примечание: Fortran хранит массивы по столбцам, C afaik хранит их по строкам. Поэтому имейте в виду, что порядок индексов будет обратным.

Я знаю, как прочитать это на Python:

 from scipy.io import FortranFile
ff = FortranFile('data.dat', 'r', '<u4')
# read the three values you are not interested in
threevals = ff.read_record('<u4')
# read the data
data = ff.read_record('<f4')
ff.close()
 

Комментарии:

1. chw21: Это очень интересно. Для позиций 0-7 я вижу 0C 00 00 00 00 00 00 00 00, хотя позиции 5-7 не имеют тех же значений, что и 1-4 при выборе. Позиции 16-19 повторяют 0-3. Как вы указали, позиции 20-23 повторяются в конце файла. Но скажите мне, что все это значит? Почему повторяющийся шаблон не наблюдается во всем файле, если он был повторен хотя бы один раз.