web-dev-qa-db-ja.com

Pythonのバイナリファイルから整数を読み取る

Pythonで [〜#〜] bmp [〜#〜] ファイルを読み取ろうとしています。最初の2バイトはBMP firm。を示しています。次の4バイトはファイルサイズです。実行すると:

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

私は得る:

ValueError:基数10のint()の無効なリテラル: 'F#\ x13'

私がやりたいのは、これらの4バイトを整数として読み取ることですが、Pythonはそれらを文字として読み取り、整数に変換できない文字列を返しているようです。正しく?

68
Manuel Aráoz

readメソッドは、バイトシーケンスを文字列として返します。文字列のバイトシーケンスからバイナリデータに変換するには、組み込みのstructモジュールを使用します: http://docs.python.org/library/struct.html

_import struct

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

unpackは常にTupleを返すので、struct.unpack('i', fin.read(4))[0]はあなたが後の整数値を与えることに注意してください。

おそらくフォーマット文字列_'<i'_を使用する必要があります(<は、リトルエンディアンのバイト順と標準のサイズとアライメントを示す修飾子です-デフォルトでは、プラットフォームのバイト順、サイズ、アライメントを使用します)。 BMP形式仕様に従って、バイトはIntel /リトルエンディアンのバイト順で書き込まれる必要があります。

109
codeape

'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リストを使用するよりもはるかに高速です。

38
Emanuel Ey

Python 3.2+以降、 from_bytes ネイティブintメソッド:

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

この関数では、数値をビッグエンディアン形式とリトルエンディアン形式のどちらでエンコードするかを指定する必要があるため、エンディアンを判断して正しく機能することを確認する必要があります。

10
CrepeGoat

structを除き、arrayモジュールも使用できます。

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

バイナリファイルを読んでいるときに、整数に展開する必要があるため、そのためにstructモジュールを使用します

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

バイナリファイルから読み取るときは、バイトと呼ばれるデータ型が使用されます。これはリストまたはタプルに少し似ていますが、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))
0
Super S