我有一个文件,其中第一个字节包含编码信息。在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
使用 numpy
就可以轻松实现:
Bytes = numpy.fromfile(filename, dtype = "uint8")
Bits = numpy.unpackbits(Bytes)
更多信息可以参考:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html
你不能逐位地读取它们 - 你必须逐字节读取它们。不过,你可以轻松地提取出每个比特:
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
加入之前的一些答案,我会使用:
[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}"用于保证完整的字节长度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'
有两种方法可以返回字节的第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
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')
f.readinto(a)
我认为这是一种更具Python风格的方式:
a = 140
binary = format(a, 'b')
我需要获取图像的位平面,这个函数帮助我编写了这个代码块:'10001100'
def img2bitmap(img: np.ndarray) -> list:
if img.dtype != np.uint8 or img.ndim > 2:
raise ValueError("Image is not uint8 or gray")
bit_mat = [np.zeros(img.shape, dtype=np.uint8) for _ in range(8)]
for row_number in range(img.shape[0]):
for column_number in range(img.shape[1]):
binary = format(img[row_number][column_number], 'b')
for idx, bit in enumerate("".join(reversed(binary))[:]):
bit_mat[idx][row_number, column_number] = 2 ** idx if int(bit) == 1 else 0
return bit_mat
同时通过这个代码块,我能够从提取的位平面生成原始图像
img = cv2.imread('test.jpg', cv2.IMREAD_GRAYSCALE)
out = img2bitmap(img)
original_image = np.zeros(img.shape, dtype=np.uint8)
for i in range(original_image.shape[0]):
for j in range(original_image.shape[1]):
for data in range(8):
x = np.array([original_image[i, j]], dtype=np.uint8)
data = np.array([data], dtype=np.uint8)
flag = np.array([0 if out[data[0]][i, j] == 0 else 1], dtype=np.uint8)
mask = flag << data[0]
x[0] = (x[0] & ~mask) | ((flag[0] << data[0]) & mask)
original_image[i, j] = x[0]
我觉得这相当快:
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
xrange(8)
改为reversed(xrange(8))
。 - user97370