web-dev-qa-db-ja.com

Pythonを使用して、バイト内のビットを読み取るにはどうすればよいですか?

最初のバイトにエンコードされた情報が含まれるファイルがあります。 Matlabでは、var = fread(file, 8, 'ubit1')を使用してバイト単位でバイトを読み取り、var(1), var(2)などで各ビットを取得できます。

Pythonに同等のビットリーダーはありますか?

32
David

ファイルからビットを読み取ります(下位ビットが最初)。

def bits(f):
    bytes = (ord(b) for b in f.read())
    for b in bytes:
        for i in xrange(8):
            yield (b >> i) & 1

for b in bits(open('binary-file.bin', 'r')):
    print b
25
user97370

作業できる最小単位はバイトです。ビットレベルで動作するには、 ビットごとの演算子 を使用する必要があります。

x = 3
#Check if the 1st bit is set:
x&1 != 0
#Returns True

#Check if the 2nd bit is set:
x&2 != 0
#Returns True

#Check if the 3rd bit is set:
x&4 != 0
#Returns False
20
Brian R. Bondy

各ビットを1つずつ読み取ることはできません。バイトごとに読み取る必要があります。ただし、ビットは簡単に抽出できます。

f = open("myfile", 'rb')
# read one byte
byte = f.read(1)
# convert the byte to an integer representation
byte = ord(byte)
# now convert to string of 1s and 0s
byte = bin(byte)[2:].rjust(8, '0')
# now byte contains a string with 0s and 1s
for bit in byte:
    print bit
10
Daniel G

numpyを使用すると、次のように簡単になります。

Bytes = numpy.fromfile(filename, dtype = "uint8")
Bits = numpy.unpackbits(Bytes)

詳細はこちら:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html

9
Mikhail V

ファイルからバイトを読み取るには:bytestring = open(filename, 'rb').read(1)。注:ファイルはbinaryモードで開かれます。

ビットを取得するには、バイト文字列を整数に変換します:_byte = bytestring[0]_(Python 3)またはbyte = ord(bytestring[0])(Python 2)そして目的のビットを抽出します:_(byte >> i) & 1_:

_>>> for i in range(8): (b'a'[0] >> i) & 1
... 
1
0
0
0
0
1
1
0
>>> bin(b'a'[0])
'0b1100001'
_
5
jfs

私が使用する以前の回答のいくつかに参加します:

[int(i) for i in "{0:08b}".format(byte)]

ファイルから読み取られた各バイトごと。 0x88バイトの例の結果は次のとおりです。

>>> [int(i) for i in "{0:08b}".format(0x88)]
[1, 0, 0, 0, 1, 0, 0, 0]

それを変数に割り当てて、最初の要求に従って動作させることができます。 「{0.08}」は、完全なバイト長を保証するためのものです

3
Francisco

バイトのi番目のビットを返すには、2つの方法があります。 「最初のビット」は、上位ビットを指すこともあれば、下位ビットを指すこともあります。

文字列とインデックスをパラメーターとして受け取り、その場所のビットの値を返す関数を次に示します。書かれているように、下位ビットを最初のビットとして扱います。最初に高位ビットが必要な場合は、指定された行のコメントを外してください。

_def bit_from_string(string, index):
       i, j = divmod(index, 8)

       # Uncomment this if you want the high-order bit first
       # j = 8 - j

       if ord(string[i]) & (1 << j):
              return 1
       else:
              return 0
_

インデックス作成は0から開始します。インデックス作成を1から開始する場合は、divmodを呼び出す前に関数のインデックスを調整できます。

使用例:

_>>> for i in range(8):
>>>       print i, bit_from_string('\x04', i)
0 0
1 0
2 1
3 0
4 0
5 0
6 0
7 0
_

さて、それがどのように機能するかについて:

文字列は8ビットのバイトで構成されているため、最初にdivmod()を使用してインデックスを複数の部分に分割します。

  • i:文字列内の正しいバイトのインデックス
  • j:そのバイト内の正しいビットのインデックス

ord()関数を使用して、_string[i]_の文字を整数型に変換します。次に、_(1 << j)_は、jで1を左シフトすることにより、j番目のビットの値を計算します。最後に、ビット単位のandを使用して、そのビットが設定されているかどうかをテストします。そうであれば1を返し、そうでなければ0を返します。

2

ビットの配列を含むbloom_filter.binというファイルがあり、ファイル全体を読み取り、配列内のそれらのビットを使用するとします。

最初に、読み取り後にビットが格納される配列を作成し、

from bitarray import bitarray
a=bitarray(size)           #same as the number of bits in the file

Openまたはwithを使用してファイルを開きます。何でも構いません...ここでopenを使い続けます。

f=open('bloom_filter.bin','rb')

ここで、すべてのビットを一度に配列「a」にロードします。

f.readinto(a)

「a」はすべてのビットを含むビット配列になりました

0
Tarun

これは非常に高速です。

import itertools
data = range(10)
format = "{:0>8b}".format
newdata = (False if n == '0' else True for n in itertools.chain.from_iterable(map(format, data)))
print(newdata) # prints tons of True and False
0
vitiral