Чтение файла SEG-Y с EBCDIC и содержимым двоичных данных в Fortran

Я читаю файл SEG-Y (используемый в геофизике для хранения данных), в котором 2 секции заголовка, первый из которых имеет размер 3200 байт и содержит информацию в формате EBCDIC, а второй заголовок имеет двоичный формат и имеет длину 400 байт. Далее следуют данные, где размер данных определяется числом, определенным в двоичном заголовке, определенном в заданных байтовых ячейках 3217-3218.

Мне удалось прочитать заголовок EBCDIC (байты 1-3200) с помощью простой команды открытия в Fortran 90 без определения доступа или формата, но я не могу пойти дальше, чтобы прочитать определенные байты в двоичном заголовке (3201-3204, 3205- 3206, ... и так далее), который содержит важную информацию, необходимую для последующего чтения остальных двоичных данных.

Как правильно определить доступ/форматирование для файла, чтобы успешно прочитать все сразу? Поддерживает ли Fortran изменение доступа к файлу/формата/... в коде? Если это невозможно, то как тогда я могу пропустить первые 3200 байт и перейти к бинарному разделу (байты 3201-3600) для чтения нужных мне данных?


person PolarXYZ    schedule 08.06.2018    source источник
comment
Добро пожаловать! Не забудьте пройти приветственный тур. Какой компилятор и операционную систему вы используете? Какая версия?   -  person Vladimir F    schedule 08.06.2018
comment
Вы читали что-нибудь о доступе stream в Fortran 2003? Ваш компилятор поддерживает это?   -  person Vladimir F    schedule 08.06.2018
comment
Я компилятор GNU fortran и работаю на машине с Linux. Не уверен, что этот компилятор поддерживает Fortran2003.   -  person PolarXYZ    schedule 08.06.2018
comment
Вы имеете в виду гфортран? Оно делает. Даже очень старые версии gfortran поддерживают потоковый доступ.   -  person Vladimir F    schedule 08.06.2018


Ответы (1)


Если вы открываете файл данных с помощью access="stream", вы можете читать файл байт за байтом с любой позиции, которую вы хотите.

character :: byte   ! integer(int8) might be a better type

open(11, file="filename",access="stream",form="unformatted",action="read",status="old")

!be careful, the positions are numbered from 1, not from 0
read(11, pos=3200) byte

Вы также можете читать другие типы данных, если они хранятся там в совместимом двоичном формате.

integer :: i
...
read(11, pos=...) i

На машине с прямым порядком байтов вам, возможно, придется преобразовать их порядок следования байтов.

person Vladimir F    schedule 08.06.2018
comment
Спасибо за ответ, я определил открытие в соответствии с вашим запросом, но меня смущает pos = 3200 в вашем заявлении о чтении. Это дает мне характер @. Я хочу прочитать следующие местоположения байтов, и все они должны дать мне целое число: 3201-3204, 3205-3208, 3209-3212, 3213-3214 и так далее. - person PolarXYZ; 08.06.2018
comment
Вы должны настроить 3200 на правильный номер, я не знаю структуру вашего файла. Это номер байта, который вы читаете, считая от 1. Он НЕ будет читать его как EBCDIC, а как собственный символ (вероятно, ASCII). Просто относитесь к нему как к байту. Вы можете прочитать 1-байтовое целое число вместо символа, но они подписаны. - person Vladimir F; 08.06.2018
comment
Мне удалось прочитать первый заголовок EBCDIC длиной 3200 байт, используя оператор чтения выше. Я проверил с помощью программного обеспечения, которое загружает один и тот же файл seg-y, и они идентичны. Затем я читаю первые байты следующего блока данных двоичного заголовка и сравниваю с тем, что читает программа, и они, к сожалению, не совпадают (все они представляют собой 2- или 4-байтовые целые числа). Любые советы о том, как разобраться с этим? - person PolarXYZ; 08.06.2018
comment
Проверьте порядок байтов/порядок байтов en.wikipedia.org/wiki/Endianness. Возможно, вам потребуется прочитать байты в целое число в правильном порядке или поменять их местами после чтения. У меня есть несколько функций для замены байтов в bitbucket.org/LadaF/elmm/src/ - person Vladimir F; 08.06.2018
comment
Спасибо за ответ. Компилятор Intel Fortran предлагает опции для замены байтов в команде open как convert='big_endian' или convert='little_endian'. Я попробовал эту опцию для прямого порядка байтов в компиляторе GNU Fortran, который я использую, и это решило мою проблему. Большое спасибо - person PolarXYZ; 11.06.2018