バイナリファイル(この場合はjpg)を読み込んでいますが、そのファイルでいくつかの値を見つける必要があります。興味のある方のために、バイナリファイルはjpgであり、バイナリ構造を 詳細はこちら として探すことで、そのサイズを選択しようとしています。
バイナリデータでFFC0を見つけ、いくつかのバイトをスキップしてから、4バイトを読み取る必要があります(これでイメージのサイズがわかります)。
バイナリデータの値を検索する良い方法は何ですか? 「検索」に相当するもの、またはreのようなものはありますか?
実際にファイルを文字列にロードし、str.find()
メソッドを使用してその文字列からバイトシーケンス0xffc0
を検索できます。任意のバイトシーケンスで機能します。
これを行うコードはいくつかの事柄に依存します。バイナリモードでファイルを開き、Python 3を使用している場合(両方ともこのシナリオではおそらくベストプラクティスです)、(文字ではなく)バイト文字列を検索する必要があります。文字列)、つまり、文字列の前にb
を付ける必要があります。
with open(filename, 'rb') as f:
s = f.read()
s.find(b'\xff\xc0')
Python 3でファイルをテキストモードで開く場合、文字列を検索する必要があります。
with open(filename, 'r') as f:
s = f.read()
s.find('\xff\xc0')
これを行う特別な理由はありませんが。以前の方法に比べて利点はありません。バイナリファイルとテキストファイルを異なる方法で処理するプラットフォーム(Windowsなど)を使用している場合、問題が発生する可能性があります。
Python 2はバイト文字列と文字列を区別しないため、そのバージョンを使用している場合、b
をb'\xff\xc0'
に含めるか除外するかは関係ありません。また、プラットフォームがバイナリファイルとテキストファイルを同じように処理する場合(MacやLinuxなど)、'r'
または'rb'
をファイルモードとして使用するかどうかは関係ありません。ただし、上位互換性のためだけに上記の最初のコードサンプルのようなものを使用することをお勧めします。Python 3に切り替えた場合に備えて、修正する必要が1つ少なくなります。
bitstring モジュールは、ほとんどこの目的のために設計されました。あなたの場合、次のコード(私はテストしていません)が説明に役立つはずです。
from bitstring import ConstBitStream
# Can initialise from files, bytes, etc.
s = ConstBitStream(filename='your_file')
# Search to Start of Frame 0 code on byte boundary
found = s.find('0xffc0', bytealigned=True)
if found:
print("Found start code at byte offset %d." % found[0])
s0f0, length, bitdepth, height, width = s.readlist('hex:16, uint:16,
uint:8, 2*uint:16')
print("Width %d, Height %d" % (width, height))
ファイル全体をメモリに読み込んで検索し、新しいファイルをディスクに書き込む代わりに、mmapモジュールを使用できます。 mmapはnotファイル全体をメモリに格納し、インプレース変更を許可します。
#!/usr/bin/python
import mmap
with open("hugefile", "rw+b") as f:
mm = mmap.mmap(f.fileno(), 0)
print mm.find('\x00\x09\x03\x03')
re
モジュールdoesは、文字列およびバイナリデータ(str
in Python 2およびbytes
in Python 3)なので、str.find
だけでなくタスクにも使用できます。
find()
メソッドは、サブルーチンの位置を知る必要がある場合にのみ使用してください。そうでない場合は、in
演算子を使用できます。次に例を示します。
with open("foo.bin", 'rb') as f:
if b'\x00' in f.read():
print('The file is binary!')
else:
print('The file is not binary!')
まあ、明らかにあります [〜#〜] pil [〜#〜] 画像モジュールには属性としてサイズがあります。あなたが提案したとおりのサイズを正確に取得したい場合は、ファイルをロードせずに、1行ずつ実行する必要があります。それを行うための最も良い方法ではありませんが、うまくいくでしょう。
Python 3.xでは、次のようにバイト文字列を別のバイト文字列で検索できます。
>>> byte_array = b'this is a byte array\r\n\r\nXYZ\x80\x04\x95 \x00\x00\x00\x00\x00'
>>> byte_array.find('\r\n\r\n'.encode())
20
>>>
Python> = 3.2の場合:
import re
f = open("filename.jpg", "rb")
byte = f.read()
f.close()
matchObj = re.match( b'\xff\xd8.*\xff\xc0...(..)(..).*\xff\xd9', byte, re.MULTILINE|re.DOTALL)
if matchObj:
# http://stackoverflow.com/questions/444591/convert-a-string-of-bytes-into-an-int-python
print (int.from_bytes(matchObj.group(1), 'big')) # height
print (int.from_bytes(matchObj.group(2), 'big')) # width