Использование Python Как я могу прочитать биты в байте? - PullRequest
32 голосов
/ 05 апреля 2010

У меня есть файл, в котором первый байт содержит закодированную информацию. В Matlab я могу прочитать бит за битом с помощью var = fread(file, 8, 'ubit1'), а затем извлечь каждый бит с помощью var(1), var(2) и т. Д.

Есть ли в python эквивалентный бит-ридер?

Ответы [ 9 ]

25 голосов
/ 05 апреля 2010

Считать биты из файла, сначала младшие биты.

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
19 голосов
/ 05 апреля 2010

Наименьшая единица измерения, с которой вы сможете работать, - это байт. Для работы на битовом уровне необходимо использовать битовые операторы .

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
10 голосов
/ 05 апреля 2010

Вы не сможете читать каждый бит по одному - вы должны читать его побайтно. Вы можете легко извлечь биты, хотя:

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
9 голосов
/ 12 мая 2015

С numpy это просто так:

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

Более подробная информация здесь:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html

5 голосов
/ 12 мая 2016

Чтобы прочитать байт из файла: bytestring = open(filename, 'rb').read(1). Примечание: файл открывается в режиме бинарный .

Чтобы получить биты, преобразуйте строку в целое число: 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'
2 голосов
/ 03 января 2017

Присоединяясь к некоторым из предыдущих ответов, я бы использовал:

[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} должен гарантировать полную длину байта

2 голосов
/ 05 апреля 2010

Существует два возможных способа вернуть i-й бит байта. «Первый бит» может относиться к старшему биту или к младшему.

Вот функция, которая принимает строку и индекс в качестве параметров и возвращает значение бита в этом месте. Как написано, он рассматривает младший бит как первый бит. Если вы хотите сначала бит старшего разряда, просто раскомментируйте указанную строку.

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. Наконец, мы используем побитовое и для проверки, установлен ли этот бит. Если это так, верните 1, в противном случае верните 0.

0 голосов
/ 15 мая 2015

Предположим, у вас есть файл 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 голосов
/ 06 ноября 2014

Это довольно быстро, я бы подумал:

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
...