41

我有一个文件,其中第一个字节包含编码信息。在 Matlab 中,我可以使用 逐位读取字节var = fread(file, 8, 'ubit1'),然后通过var(1), var(2)等检索每个位。

python中是否有任何等效的位阅读器?

4

10 回答 10

34

从文件中读取位,首先是低位。

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
于 2010-04-05T08:22:42.030 回答
27

您可以使用的最小单位是一个字节。要在位级别工作,您需要使用位运算符

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
于 2010-04-05T02:58:18.017 回答
14

就像numpy这样很容易:

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

更多信息在这里:
http ://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html

于 2015-05-12T17:26:13.110 回答
12

您将无法逐位读取 - 您必须逐字节读取。不过,您可以轻松地提取这些位:

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
于 2010-04-05T03:30:10.073 回答
10

加入我会使用的一些以前的答案:

[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}”是为了保证全字节长度

于 2017-01-03T05:15:00.420 回答
6

从文件中读取一个字节: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'
于 2016-05-12T14:16:43.793 回答
2

返回字节的第 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()函数将字符 atstring[i]转换为整数类型。然后,(1 << j)通过将 1 左移 来计算第 j 位的值j。最后,我们使用按位与来测试该位是否已设置。如果是则返回 1,否则返回 0。

于 2010-04-05T03:52:45.607 回答
1

假设您有一个名为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' 现在是一个包含所有位的位数组

于 2015-05-15T08:34:37.483 回答
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
于 2014-11-06T19:44:19.243 回答
0

我认为这是一种更 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]
于 2022-03-05T00:55:42.477 回答