我有四个整数{a
,b
,c
,d
},它们可以包含以下值范围:
a
- {0或1}(1位)
b
- {0或1}(1位)
c
- {0,1,2,...,7}(3位)
d
- {0,1,2,...,7}(3位)
首先,我想将它们打包成一个字节,然后写入二进制文件。
稍后,我想解压缩一个字节并从中获取格式的元组(a
,b
,c
,d
)。
我知道如何在python中读取/写入二进制文件的字节。但是如何进行打包/拆包?
答案 0 :(得分:31)
使用shift和按位OR,然后转换为字符以获得“byte”:
x = chr(a | (b << 1) | (c << 2) | (d << 5))
要再次解压缩该字节,首先转换为整数,然后移位并使用按位AND:
i = ord(x)
a = i & 1
b = (i >> 1) & 1
c = (i >> 2) & 7
d = (i >> 5) & 7
说明:最初,你有
0000000a
0000000b
00000ccc
00000ddd
左转给你
0000000a
000000b0
000ccc00
ddd00000
按位OR导致
dddcccba
转换为字符会将其转换为单个字节。
解包:四个不同的右移导致
dddcccba
0dddcccb
00dddccc
00000ddd
使用1
(0b00000001
)或7
(0b00000111
)屏蔽(按位AND)会导致
0000000a
0000000b
00000ccc
00000ddd
试。
答案 1 :(得分:10)
def encode(a, b, c, d):
return a | b << 1 | c << 2 | d << 5
def decode(x):
return x & 1, (x >> 1) & 1, (x >> 2) & 7, (x >> 5) & 7
答案 2 :(得分:5)
如果你需要这么多东西,那么位移会变得乏味且容易出错。有第三方库可以提供帮助 - 我写了一个名为bitstring的文件:
打包并转换为字节:
x = bitstring.pack('2*uint:1, 2*uint:3', a, b, c, d).bytes
并解压缩:
a, b, c, d = bitstring.BitArray(bytes=x).unpack('2*uint:1, 2*uint:3')
这对你的例子来说可能有点过头了,但是当事情变得更复杂时它会很有用。
答案 3 :(得分:4)
非常简单。面具(范围),将它们移动到位,或者它们在一起。
packed = ((a & 1) << 7) | ((b & 1) << 6) | ((c & 7) << 3) | (d & 7)
a = (packed >> 7) & 1
b = (packed >> 6) & 1
c = (packed >> 3) & 7
d = packed & 7