2009-07-22 12 views
54

私はPythonでBMPファイルを読み込もうとしています。私は最初の2バイトを知っています はBMP会社を示しています。次の4バイトはファイルサイズです。私はexcecute時:Pythonでバイナリファイルから整数を読む

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

私は整数としてこれら4つのバイトを読んでいる私は何をしたい

ValueError: invalid literal for int() with base 10: 'F#\x13'

を得る... Pythonは文字としてそれらを読んで、文字列を返し、どのようです整数に変換することはできません。どうやってこれを正しく行うことができますか?

+2

自分のBMPライブラリを書くのに時間を費やすのではなく、ビットマップを使用するのが目標です(楽しいとは言えませんが...)。PIL http://www.pythonware.com/あなたがすでにインストールしているかもしれない/ products/pil /試してみよう:画像をインポート –

+4

ありがとうJared、しかし私はbmpを手で読むことを楽しみにしていました! ) –

答えて

88

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'を使用する必要があります(<は、リトルエンディアンのバイトオーダーと標準サイズとアライメントを表す修飾子です - デフォルトでは、プラットフォームのバイト順序、サイズとアライメントを使用することです)。 BMPフォーマット仕様によれば、バイトはインテル/リトルエンディアンのバイトオーダーで書かれていなければならない。

+18

'i = struct.unpack(...)[0]'を書くのではなく、 'i、= struct.unpack(...)'と書いています。 –

+0

@Otto他の?論理的な違いはありますか? – Caltor

+1

私は、Pythonのファイルから整数(またはShortsなど)を読み込む組み込み関数がないことは非常に驚きです。私はJavaの専門家ではありませんが、これを行うreadUnsignedShort()などのネイティブ関数があると思います。 – Caltor

4

あなたがバイナリファイルを読んでいると、あなたは整数にそれを解凍する必要があり、そうstruct以外は

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

struct.unpackはタプルを返す – luc

+0

@luc、ありがとう、固定 –

6

のためのstructモジュールを使用します。また、arrayモジュール

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

良い点。しかし、この解決策はstructモジュールの柔軟性ほど柔軟ではありません。これは、values.read()で読み取られるすべての要素が長整数でなければならないためです(長い整数、1バイト、次に長い整数を読み込むのは便利ではありません。アレイモジュール)。 – EOL

+0

私は同意します。 'array'は、バイナリファイルを読み込む効率的な方法ですが、正しく言及したように、構造体を扱うときに非常に柔軟性がありません。 –

+1

array.readはarray.fromfileの方が1.51から –

31

アンを使用することができます'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を参照してください。

Pythonリストを使用するよりもはるかに高速であるため、NumPyを使用して配列/行列データを処理する方が個人的に好きです。

+5

へと非難されました。ファイルのオープンはスキップできます: 'a = np.fromfile( 'file.bin'、dtype = np.uint32)' – MathieuS

2

のPython 3.2以上のとおり、あなたもfrom_bytesネイティブint型メソッド使用して、これを達成することができます

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

(注)この機能は数がビッグエンディアンかリトルエンディアン形式でエンコードされているかどうかを指定する必要があることは、 、正しく動作することを確認するためにエンディアンを決定する必要があります。

関連する問題