Python의 바이너리 파일에서 정수 읽기


83

Python에서 BMP 파일 을 읽으려고합니다 . 처음 두 바이트는 BMP 회사를 나타냅니다. 다음 4 바이트는 파일 크기입니다. 내가 실행할 때 :

fin = open("hi.bmp", "rb")
firm = fin.read(2)  
file_size = int(fin.read(4))  

나는 얻다:

ValueError : 10 진수 인 int ()에 대한 잘못된 리터럴 : 'F # \ x13'

내가하고 싶은 것은 그 4 바이트를 정수로 읽는 것이지만, 파이썬은 그것들을 문자로 읽고 정수로 변환 할 수없는 문자열을 반환하는 것 같습니다. 이 작업을 올바르게 수행하려면 어떻게해야합니까?


2
자신의 BMP 라이브러리를 작성하는 데 시간을 소비하는 대신 비트 맵 을 사용 하는 것이 목표라면 (재미있게 들리지 않는 것이 아닙니다 ...) 이미 설치했을 수있는 PIL pythonware.com/products/pil 을 사용할 수 있습니다 . 시도 : 이미지 가져 오기
Jared Updike 2009-07-22

7
Jared에게 고마워요.하지만 재미를 위해서만 수동으로 bmp를 읽고 싶었습니다! :)
Manuel Araoz

답변:


123

read메서드는 바이트 시퀀스를 문자열로 반환합니다. 문자열 바이트 시퀀스에서 바이너리 데이터로 변환하려면 내장 struct모듈 http://docs.python.org/library/struct.html을 사용하십시오 .

import struct

print(struct.unpack('i', fin.read(4)))

참고 unpack항상 튜플을 반환, 그래서 struct.unpack('i', fin.read(4))[0]당신이 후하다는 정수 값을 제공합니다.

아마도 형식 문자열을 사용해야합니다 '<i'(<는 little-endian 바이트 순서와 표준 크기 및 정렬을 나타내는 수정 자입니다. 기본값은 플랫폼의 바이트 순서, 크기 및 정렬을 사용하는 것입니다). BMP 형식 사양에 따라 바이트는 Intel / little-endian 바이트 순서로 작성해야합니다.


22
글을 쓰는 대신 i = struct.unpack(...)[0]자주 글을 씁니다i, = struct.unpack(...)
Otto Allmendinger

@Otto 한 가지 방법을 선호하는 이유가 있습니까? 논리적 차이가 있습니까?
Caltor

2
파이썬의 파일에서 정수 (또는 Shorts 등)를 읽는 내장 함수가 없다는 것은 매우 놀랍습니다. 나는 Java 전문가는 아니지만 readUnsignedShort ()와 같은 기본 기능이 있다고 생각합니다.
Caltor

@codeape [0]이 (가) 무엇을하고 있는지 또는 적어도 어떤 유형의 언어 요소인지 정의 할 수 있습니까? 즉시 명확하지 않으며 Python 문서에서 검색하는 것은 거의 불가능합니다.
Caltor 2010 년

목록과 튜플의 경우 obj [N]은 obj의 N 번째 요소를 가져옵니다. 참조 docs.python.org/tutorial/introduction.html#lists
codeape

50

'struct.unpack ()'을 사용하지 않는 대체 방법은 NumPy 를 사용하는 것입니다 .

import numpy as np

f = open("file.bin", "r")
a = np.fromfile(f, dtype=np.uint32)

'dtype'은 데이터 유형을 나타내며 int #, uint #, float #, complex # 또는 사용자 정의 유형이 될 수 있습니다. 을 참조하십시오 numpy.fromfile.

개인적으로 NumPy를 사용하여 배열 / 행렬 데이터로 작업하는 것을 선호합니다. Python 목록을 사용하는 것보다 훨씬 빠릅니다.


13
파일 열기를 건너 뛸 수 있습니다.a = np.fromfile('file.bin', dtype=np.uint32)
Mathieu Schopfer 2015 년

17

Python 3.2 이상에서는 from_bytes기본 int 메서드를 사용하여이 작업을 수행 할 수도 있습니다 .

file_size = int.from_bytes(fin.read(2), byteorder='big')

이 함수를 사용하려면 숫자가 빅 엔디안 형식인지 리틀 엔디안 형식인지 지정해야하므로 제대로 작동하는지 확인하려면 엔디안 형식을 결정해야합니다.


6

모듈 struct을 사용할 수도 있다는 점을 제외하고array

import array
values = array.array('l') # array of long integers
values.read(fin, 1) # read 1 integer
file_size  = values[0]

좋은 지적. 그러나이 솔루션은 values.read ()를 통해 읽는 모든 요소가 긴 정수 여야하기 때문에 struct 모듈만큼 유연하지 않습니다. 어레이 모듈).
Eric O Lebigot

나는 동의한다. array이진 파일을 읽는 효율적인 방법이지만 올바르게 언급했듯이 구조를 다루어야 할 때 그다지 유연하지 않습니다.
Nick Dandoulakis

1
array.read는 1.51 이후부터 array.fromfile 대신 사용되지 않습니다

4

바이너리 파일을 읽을 때 정수로 압축을 풀어야하므로이를 위해 struct 모듈을 사용하십시오.

import struct
fin = open("hi.bmp", "rb")
firm = fin.read(2)  
file_size, = struct.unpack("i",fin.read(4))

반환에게 튜플 struct.unpack

1

이진 파일에서 읽을 때 바이트라는 데이터 유형이 사용됩니다. 이것은 0에서 255 사이의 정수만 저장할 수 있다는 점을 제외하면 목록 또는 튜플과 비슷합니다.

시험:

file_size = fin.read(4)
file_size0 = file_size[0]
file_size1 = file_size[1]
file_size2 = file_size[2]
file_size3 = file_size[3]

또는:

file_size = list(fin.read(4))

대신에:

file_size = int(fin.read(4))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.