Чтение двоичного файла с помощью python


Я нахожу особенно трудным чтение двоичного файла с Python. Ты можешь мне помочь? Мне нужно прочитать этот файл, который в Fortran 90 легко читать

int*4 n_particles, n_groups
real*4 group_id(n_particles)
read (*) n_particles, n_groups
read (*) (group_id(j),j=1,n_particles)

в деталях формат файла:

Bytes 1-4 -- The integer 8.
Bytes 5-8 -- The number of particles, N.
Bytes 9-12 -- The number of groups.
Bytes 13-16 -- The integer 8.
Bytes 17-20 -- The integer 4*N.
Next many bytes -- The group ID numbers for all the particles.
Last 4 bytes -- The integer 4*N. 

Как я могу прочитать это в Python? Я пробовал все, но это никогда не работало. Есть ли шанс, что я могу использовать программу f90 в python, читая этот двоичный файл, а затем сохранить данные, которые мне нужно использовать?

4 69

4 ответа:

прочитайте содержимое двоичного файла следующим образом:

with open(fileName, mode='rb') as file: # b is important -> binary
    fileContent = file.read()

затем "распаковать" двоичные данные с помощью структура.распакуйте:

старт байт: struct.unpack("iiiii", fileContent[:20])

тело: игнорировать заголовочные байты и конечный байт (= 24); оставшаяся часть образует тело, чтобы узнать количество байтов в теле сделать целочисленное деление на 4; полученный фактор умножается на строку 'i' создать правильный формат для распаковки метод:

struct.unpack("i" * ((len(fileContent) -24) // 4), fileContent[20:-4])

конечный байт: struct.unpack("i", fileContent[-4:])

В общем, я бы рекомендовал вам изучить использование Python struct модуль для этого. Это стандартно для Python, и должно быть легко перевести спецификацию вашего вопроса в строку форматирования, подходящую для struct.unpack().

обратите внимание, что если есть "невидимое" заполнение между / вокруг полей, вам нужно будет выяснить это и включить его в unpack() вызова, или вы будете читать чужие биты.

чтение содержимого файла в чтобы иметь что-то, чтобы распаковать довольно тривиально:

import struct

data = open("from_fortran.bin", "rb").read()

(eight, N) = struct.unpack("@II", data)

это распаковывает первые два поля, предполагая, что они начинаются в самом начале файла (без заполнения или посторонних данных), а также предполагая собственный порядок байтов (@ символ). Элемент Is в строке форматирования означает "целое число без знака, 32 бита".

вы могли бы использовать numpy.fromfile, который может считывать данные как из текстовых, так и из двоичных файлов. Сначала вы создадите тип данных, который представляет ваш формат файла, используя numpy.dtype, а затем прочитать этот тип из файла с помощью numpy.fromfile.

import pickle
f=open("filename.dat","rb")
try:
    while True:
        x=pickle.load(f)
        print x
except EOFError:
    pass
f.close()