我有一个文件,其中第一个字节包含编码信息。 在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)
。注意:文件以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'
有两种可能的方法返回字节的第 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)
通过左移1j
来计算第j位的值。 最后,我们使用按位与来测试该位是否已设置。 如果是则返回 1,否则返回 0。
假设您有一个名为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' 现在是包含所有位的位数组
我认为这相当快:
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
我认为这是一种更Pythonic的方式:
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]
您可以使用ReverseBox
例如,如果您想从 number 2273 获取 位置 5 上的 3 位,您可以编写如下内容:
from reversebox.io_files.bytes_helper_functions import get_bits
result = get_bits(2273, 3, 5)
print(result)
结果:
7