Acho particularmente difícil ler arquivos binários com Python. Você pode me dar a mão? Eu preciso ler este arquivo, que em Fortran 90 é facilmente lido por
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)
Em detalhes, o formato do arquivo é:
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.
Como posso ler isso com Python? Tentei de tudo, mas nunca funcionou. Existe alguma chance de eu usar um programa f90 em python, lendo este arquivo binário e salvar os dados que preciso usar?
fromfile
função do Numpy facilita a leitura de arquivos binários. Eu recomendo.Respostas:
Leia o conteúdo do arquivo binário assim:
em seguida, "descompacte" os dados binários usando struct.unpack :
Os bytes iniciais:
struct.unpack("iiiii", fileContent[:20])
O corpo: ignore os bytes do cabeçalho e o byte final (= 24); A parte restante forma o corpo, para saber o número de bytes no corpo faça uma divisão inteira por 4; O quociente obtido é multiplicado pela string
'i'
para criar o formato correto para o método de descompactação:O byte final:
struct.unpack("i", fileContent[-4:])
fonte
import struct
Em geral, eu recomendo que você use o módulo struct do Python para isso. É padrão com Python e deve ser fácil traduzir a especificação de sua pergunta em uma string de formatação adequada para
struct.unpack()
.Observe que, se houver um preenchimento "invisível" entre / ao redor dos campos, você precisará descobrir isso e incluí-lo na
unpack()
chamada, ou lerá os bits errados.Ler o conteúdo do arquivo para ter algo para descompactar é bastante trivial:
Isso descompacta os dois primeiros campos, supondo que eles comecem no início do arquivo (sem preenchimento ou dados estranhos) e também assumindo a ordem de byte nativa (o
@
símbolo). OsI
s na string de formatação significam "inteiro sem sinal, 32 bits".fonte
Você pode usar o
numpy.fromfile
, que pode ler dados de arquivos de texto e binários. Primeiro, você construiria um tipo de dados, que representa seu formato de arquivo, usandonumpy.dtype
, e depois leria esse tipo do arquivo usandonumpy.fromfile
.fonte
Para ler um arquivo binário para um
bytes
objeto:Para criar um
int
dos bytes 0-3 dos dados:Para descompactar vários
int
s dos dados:pathlib
int.from_bytes()
struct
fonte
Eu também achei Python deficiente quando se trata de ler e escrever arquivos binários, então escrevi um pequeno módulo (para Python 3.6+).
Com binaryfile você faria algo assim (estou supondo, já que não conheço Fortran):
O que produz uma saída como esta:
Usei skip () para pular os dados adicionais que o Fortran adiciona, mas você pode querer adicionar um utilitário para lidar com os registros Fortran corretamente. Se você fizer isso, uma solicitação de pull será bem-vinda.
fonte
fonte
pickle.load
carrega? Ele carrega um fluxo Fortran, arquivos diretos ou sequenciais? Eles são diferentes e não compatíveis.