python2.7 - 写入磁盘时将布尔值存储为单个位



我正在编写将整数转换为填充的 8 位字符串的代码。然后我想将这些字符串写入二进制文件。我在确定与当前使用的 numpy 数组一起使用的正确dtype时遇到问题。

在下面的代码中,当我使用 dtype=np.int8 设置bin_data变量时,输出为:

$ python bool_dtype.py 
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
[0 0 0 0 1 0 0 0 0]
16

bin_data设置为 dtype=np.bool_ 时,输出始终为 true,如下所示:

$ python bool_dtype.py 
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 0, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
a[j] = 1, bool(a[j]) = True
[ True  True  True  True  True  True  True  True  True]
16

当我在使用dtype=np.int8时查看数据的 xxd 转储时,我看到一个预期的字节用于表示每个位 (1,0( IE 00000001或 00000000。使用dtype=np.bool_会导致同样的问题。

所以我的两个主要问题是

  1. 为什么布尔值在读取数组元素时总是读取为 True。

  2. 当我将数据写入文件时,如何更有效地存储数据,以便单个位存储为字节,而只是连接到前一个元素?

这是有问题的代码,谢谢!

#!/usr/bin/python2.7
import numpy as np
import os
# x = np.zeros(200,dtype=np.bool_)
# for i in range(0,len(x)):
#     if i%2 != 1:
#         x[i] = 1
data_size = 2
data = np.random.randint(0,9,data_size)
tx=''
for i in range(0,data_size):
    tx += chr(data[i])
data = tx
a = np.zeros(8,dtype=np.int8)
bin_data = np.zeros(len(data)*8,dtype=np.bool_)
# each i is a character byte in data string
for i in range(0,len(data)):
    # formats data in 8bit binary without the 0b prefix
    a = format(ord(data[i]),'b').zfill(8)
    for j in range(0,len(a)):
        bin_data[i*len(a) + j] = a[j]
        print("a[j] = {}, bool(a[j]) = {}").format(a[j], bool(a[j]))
print bin_data[1:10]
print len(bin_data)
path = os.getcwd()
path = path + '/bool_data.bin'
data_file = open(path, "wb")
data_file.write(bin_data)
data_file.close()

编辑:

我希望在使用dtype=np.bool_时看到什么

>>> import numpy as np
>>> a = np.zeros(2,dtype=np.bool_)
>>> a
array([False, False], dtype=bool)
>>> a[1] = 1
>>> a
array([False,  True], dtype=bool)
  1. bool 总是返回 true 的原因是 a[j] 是一个非空字符串。在使用 bool 进行测试之前(以及在将其作为 numpy bool 数组的条目之前(,您需要将 a[j] 转换为 int。
  2. 你可以调用numpy.packbits将布尔数组压缩成uint8数组(如果需要,它会为你填充(,然后调用numpy.unpackbits来反转操作。

编辑:

如果布尔数组的长度不是 8 的倍数,则在打包和解包后,数组将填充为零,以使长度成为 8 的倍数。在这种情况下,您有两种选择:

  1. 如果可以安全地截断数据以具有可被 8 整除的位数,请执行此操作。像这样:data=data[:8*(len(data)/8)]
  2. 如果您负担不起截断,那么您将以某种方式记录有意义的位数。我建议使打包数据的第一个字节等于有意义的位数 mod 8。这只会增加一个字节的内存开销,并且不会增加太多的计算时间。像这样:

包装

bool_data = np.array([True, True, True])
nbits = len(bool_data)
rem = nbits % 8
nbytes = nbits/8
if rem: nbytes += 1
data = np.empty(1+nbytes, dtype=np.uint8)
data[0] = rem
data[1:] = np.packbits(bool_data)

打开

rem = data[0]
bool_data = np.unpackbits(data[1:])
if rem:
  bool_data = bool_data[:-(8-rem)]

相关内容

  • 没有找到相关文章

最新更新