파이썬으로 바이너리 파일 읽기


104

파이썬으로 바이너리 파일을 읽는 것이 특히 어렵다는 것을 알게되었습니다. 날 도와 줄수 있습니까? 이 파일을 읽어야합니다. 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. 

파이썬으로 어떻게 읽을 수 있습니까? 나는 모든 것을 시도했지만 결코 효과가 없었습니다. 파이썬에서 f90 프로그램을 사용하여이 바이너리 파일을 읽은 다음 필요한 데이터를 저장할 가능성이 있습니까?


1
이 파일이 Fortran 프로그램에 의해 작성 되었습니까? 그렇다면 Fortran은 기본적으로 파일에 기록하는 각 레코드 앞에 추가 데이터를 추가하기 때문에 어떻게 작성 되었습니까? 데이터를 읽을 때주의해야 할 수도 있습니다.
Chris

1
내 이전 의견을 무시하십시오. intergers 8 및 4 * N은 분명히이 추가 데이터입니다.
Chris

2
또한 python에서 바이너리 파일 읽기 질문에 대한 답변을 참조하십시오 .
Chris

Numpy의 fromfile기능을 사용하면 바이너리 파일을 쉽게 읽을 수 있습니다. 난 그것을 추천 해.
littleO

... 그리고 항상 당신의 엔디안을 조심하세요. 다른 제조업체의 컴퓨터간에 이식 할 때.
DragonLord

답변:


154

이진 파일 내용을 다음과 같이 읽으십시오.

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

그런 다음 struct.unpack을 사용하여 이진 데이터를 "압축 해제"합니다 .

시작 바이트 : struct.unpack("iiiii", fileContent[:20])

본문 : 표제 바이트와 후행 바이트 무시 (= 24); 나머지 부분은 본문을 형성하고 본문의 바이트 수를 알기 위해 정수를 4로 나눕니다. 얻은 몫에 문자열 'i'을 곱하여 unpack 메서드에 대한 올바른 형식을 만듭니다.

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

끝 바이트 : struct.unpack("i", fileContent[-4:])


이 다른 포스트 좀 봐주 시겠어요? stackoverflow.com/questions/8092469/… ... 또 다른 바이너리 파일을 읽으려고했지만이 경우에는 바이트 구조를 자세히 알지 못합니다. 예를 들어 때때로 정수 8이 있다는 것을 알아 냈습니다. 그러나 IDL을 사용하면이 데이터를 읽는 것이 정말 간단합니다. 파이썬으로 똑같이 할 수 있습니까?
Brian

게시 된 답변과 댓글이 만족스럽지 않은 이유를 여기가 아닌 다른 게시물 안에 표시해주세요. 더 자세한 정보를 제공하기 위해 질문을 업데이트해야 할 수도 있습니다. 업데이트 될 때 살펴 보겠습니다.
gecco

압축을 푼 char []를 문자열로 변환해야하는 경우이 답변을 참조하십시오 .
PeterM

import struct
JW

23

일반적으로 이를 위해 Python의 struct 모듈을 사용하는 것이 좋습니다 . Python의 표준이며 질문의 사양을 .NET에 적합한 형식 지정 문자열로 쉽게 변환 할 수 있어야합니다 struct.unpack().

필드 사이 / 주위에 "보이지 않는"패딩이있는 경우이를 파악하여 unpack()호출에 포함해야합니다 . 그렇지 않으면 잘못된 비트를 읽게됩니다.

압축을 풀기 위해 파일의 내용을 읽는 것은 매우 간단합니다.

import struct

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

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

이렇게하면 파일의 맨 처음 (패딩 또는 관련없는 데이터 없음)에서 시작하고 기본 바이트 순서 ( @기호)를 가정한다고 가정하고 처음 두 필드의 압축을 풉니 다 . I형식화 문자열 의 s는 "부호없는 정수, 32 비트"를 의미합니다.


좋아,하지만 파일의 바이트를 읽는 방법도 모르겠다. 내 질문에서 파일을 바이트 5에서 8까지 읽고 결과를 정수로 변환하려면 어떻게해야합니까? 죄송합니다. 저는 Python을 처음 사용합니다.
Brian


11

바이너리 파일을 bytes객체로 읽으려면 :

from pathlib import Path
data = Path('/path/to/file').read_bytes()  # Python 3.5+

int데이터의 0-3 바이트에서 생성하려면 :

i = int.from_bytes(data[:4], byteorder='little', signed=False)

int데이터에서 여러 s의 압축을 풀려면 :

import struct
ints = struct.unpack('iiii', data[:16])

0

나도 바이너리 파일을 읽고 쓸 때 파이썬이 부족하다는 것을 알았으므로 작은 모듈 (Python 3.6 이상용)을 작성했습니다.

binaryfile 을 사용하면 다음과 같이 할 수 있습니다 (Fortran을 모르기 때문에 추측합니다).

import binaryfile

def particle_file(f):
    f.array('group_ids')  # Declare group_ids to be an array (so we can use it in a loop)
    f.skip(4)  # Bytes 1-4
    num_particles = f.count('num_particles', 'group_ids', 4)  # Bytes 5-8
    f.int('num_groups', 4)  # Bytes 9-12
    f.skip(8)  # Bytes 13-20
    for i in range(num_particles):
        f.struct('group_ids', '>f')  # 4 bytes x num_particles
    f.skip(4)

with open('myfile.bin', 'rb') as fh:
    result = binaryfile.read(fh, particle_file)
print(result)

다음과 같은 출력이 생성됩니다.

{
    'group_ids': [(1.0,), (0.0,), (2.0,), (0.0,), (1.0,)],
    '__skipped': [b'\x00\x00\x00\x08', b'\x00\x00\x00\x08\x00\x00\x00\x14', b'\x00\x00\x00\x14'],
    'num_particles': 5,
    'num_groups': 3
}

Fortran이 추가하는 추가 데이터를 건너 뛰기 위해 skip ()을 사용했지만 대신 Fortran 레코드를 올바르게 처리하는 유틸리티를 추가 할 수 있습니다. 그렇게한다면 풀 리퀘스트를 환영합니다.


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

6
아마도 이것이 다른 답변보다 (또는 적어도만큼 좋은) 이유에 대한 작은 설명의 가치가 있습니다.
Phil

2
포트란 생성 바이너리와 함께 작동하는지 확인 했습니까?
agentp dec

1
또한 그것이 무엇을하는지 설명하십시오 ... 피클은 무엇입니까? pickle.load로드 는 무엇입니까 ? Fortran 스트림, 직접 또는 순차 파일을로드합니까? 그들은 다르며 호환되지 않습니다.
Vladimir F
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.