У меня есть файл, в котором первый байт содержит закодированную информацию. В Matlab я могу почитать бит по порядку с var = fread(file, 8, 'ubit1')
, а затем получить каждый бит var(1), var(2)
и т.д.
Есть ли эквивалентный бит-ридер в python?
У меня есть файл, в котором первый байт содержит закодированную информацию. В Matlab я могу почитать бит по порядку с var = fread(file, 8, 'ubit1')
, а затем получить каждый бит var(1), var(2)
и т.д.
Есть ли эквивалентный бит-ридер в python?
Прочитайте биты из файла, сначала первые бит.
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
Самый маленький блок, с которым вы сможете работать, - это байт. Чтобы работать на уровне бит, вам нужно использовать побитовые операторы.
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
Вы не сможете читать каждый бит один за другим - вам нужно прочитать его байтом по байт. Вы можете легко извлечь биты, но:
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
С numpy
это легко:
Bytes = numpy.fromfile(filename, dtype = "uint8")
Bits = numpy.unpackbits(Bytes)
Подробная информация здесь:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html
Чтобы прочитать байт из файла: bytestring = open(filename, 'rb').read(1)
. Примечание: файл открывается в двоичном режиме.
Чтобы получить бит, преобразуйте bytestring в целое число: 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'
Существует два возможных способа вернуть 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.
Присоединяясь к некоторым из предыдущих ответов, я бы использовал:
[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}" должен гарантировать полную длину байта
Это довольно быстро, я бы подумал:
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
Предположим, что у вас есть файл bloom_filter.bin, который содержит массив бит, и вы хотите прочитать весь файл и использовать эти биты в массиве.
Сначала создайте массив, в котором бит будет сохранен после чтения,
from bitarray import bitarray
a=bitarray(size) #same as the number of bits in the file
Откройте файл, используя open или with, все в порядке... Я придерживаюсь открытого здесь,
f=open('bloom_filter.bin','rb')
Теперь загрузите все биты в массив "a" одним выстрелом, используя
f.readinto(a)
'a' теперь представляет собой битаррей, содержащий все биты