如何将 4 个字节的二进制数据解包为 3 个字节和 1 个字节的值?

How to unpack 4 bytes of binary data as 3 byte and 1 byte values?

我有 4 个字节的二进制数据(大端)要解压。如果它包含两个 2 字节无符号整数值,这将很简单:

a, b = data.unpack("C>C>")

但是如果数据包含一个 3 字节值 (a) 后跟一个 1 字节值 (b) 怎么办? unpack 方法似乎无法处理 8、16、32 和 64 位整数以外的格式。这是我想出的:

a, b = data.unpack("L>XC")   # "L>": unpack a 32-bit unsigned int (big-endian)
                             # "X":  rewind (skip back) one byte
                             # "C":  unpack an 8-bit unsigned int
a >>= 8                      # drop the last (lowest) byte from a

(如果数据是小尾数法,a &= 0xFFFFFF 可用于删除最后(最高)字节。)

是否有更优雅的方式来解压这些值?

这是一个合理的方式。另一种方式(不涉及备份)是

a, b, c = data.unpack("S>CC") # C doesn't have endianness
ab = a << 8 + b

由于您的值是无符号的,因此将它们粘在一起时无需担心符号扩展。

为了完整起见,您也可以反其道而行之 — 解压缩单个 32 位 int 并使用位操作将其拆分。

ab, = data.unpack("L>")
a, b = ab >> 8, ab & 0xFF

@hobbs 有一个很好的答案。我只是想提一下,您也可以在这种情况下使用 Numeric#divmod

ab, = data.unpack('L>')
a, b = ab.divmod(2**8)

或者只是:

a, b = data.unpack('L>')[0].divmod(2**8)