如何存储和 write/load to/from 文件任意位数?

How to store and write/load to/from file an arbitrary number of bits?

我想编写一个哈希函数,返回 3 个整数 a、b、c 的哈希值。我希望能够选择编码每个整数的位数并将它们连接起来。例如:

a=60  (8 bits) -> 00111100
b=113 (8 bits) -> 01110001
c=5   (4 bits) -> 0101

应该给

00111100011100010101

即20 位。

给定 a、b 和 c 作为整数(60、113 和 5)以及每个整数允许的位数(8、8 和 4),我如何获取哈希并将其存储在 python 对象的总大小(20 位),并且 write/load 它到一个文件?

这里有一个 class 可以将任意数量的位写入类似文件的对象。完成后调用 flush

class bitwriter():
    def __init__(self, f):
        self.f = f
        self.bits = 0
        self.count = 0
    def write(self, value, bitcount):
        mask = (1 << bitcount) - 1
        self.bits = (self.bits << bitcount) | (value & mask)
        self.count += bitcount
        while self.count >= 8:
            byte = self.bits >> (self.count - 8)
            self.f.write(byte, 1)
            self.count -= 8
            self.bits &= (1 << self.count ) - 1
    def flush(self):
        if self.count != 0:
            byte = self.bits << (8 - count)
            self.f.write(byte, 1)
        self.bits = self.count = 0
        self.f.flush()

我认为这符合您的要求。它使用我的另一个答案中引用的 bitio 模块来 write/read 位 to/from 文件。

操作系统通常要求文件大小为 8 位的倍数,因此这最终会创建一个 24 位(3 字节)的文件来存储单个 20 位值。每 20 位值 16.7% 的开销就不会发生,当然,如果你写了几个,一个接一个地写,并且直到最后一个之后才调用 flush()

import bitio  # see 

# hash function configuration
BW = 8, 8, 4  # bit widths of each integer
HW = sum(BW)  # total bit width of hash

def myhash(a, b, c):
    return (((((a & (2**BW[0]-1)) << BW[1]) |
                b & (2**BW[1]-1)) << BW[2]) |
                c & (2**BW[2]-1))

hashed = myhash(60, 113, 5)
print('{:0{}b}'.format(hashed, HW))  # --> 00111100011100010101

with open('test.bits', 'wb') as outf:
    bw = bitio.BitWriter(outf)
    bw.writebits(hashed, HW)
    bw.flush()

with open('test.bits', 'rb') as inf:
    br = bitio.BitReader(inf)
    val = br.readbits(HW)

print('{:0{}b}'.format(val, HW))  # --> 00111100011100010101