我有一个bytearray
,例如[0x6B, 0x6A, 0x6D, 0x6C]
。
出于无法控制的原因,字节“不正确”,需要修复。我想要的输出是像bytearray
这样的[0xAB, 0xCD]
。
因此,在我的示例中,我想忽略字节的“ 6”部分。 (6仅是示例,它可以更改)。
我目前正在通过以下方式这样做:
'6B6A'
'AB'
'AB'
十六进制字符串转换为字节我已经有一个可行的解决方案,但是使用带有数字值的字符串操作感觉很“错误”。
我不擅长按位运算符,也不确定是否可以使用按位运算符或完全其他方式来以更快和/或更有效的方式执行此操作。
答案 0 :(得分:3)
一次遍历字节数组2个项目,并使用位操作组合每个字节的最低4位:
result = bytearray()
it = iter([0x6B, 0x6A, 0x6D, 0x6C])
for a, b in zip(it, it):
a &= 0x0F
b = (b & 0x0F) << 4
result.append(b|a)
>>> result
bytearray(b'\xab\xcd')
或更简洁地理解为列表:
it = iter([0x6B, 0x6A, 0x6D, 0x6C])
result = bytearray((b & 0x0F) << 4 | (a & 0x0F) for a, b in zip(it, it))
>>> result
bytearray(b'\xab\xcd')
答案 1 :(得分:1)
如果模式始终相同,则可以
l = [0x6B, 0x6A, 0x6D, 0x6C]
packed = [k[0] & 0x0F | ((k[1] & 0x0F) << 4) for k in (l[c:c:+2] for c in range(0, len(l), 2))]
assert packed == [0xAB, 0xCD]
这将遍历字节对,将第一个字节的低半字节用作最终字节的低半字节,将第二个字节的高半字节用作最终字节的高半字节。
答案 2 :(得分:1)
这是一个不使用按位运算符的答案。
如果您知道数字始终在0..255范围内(并且它们应该是字节),那么您可以使用乘法(而不是 shift-左),余数(而不是 bitwise-and )和 sum (而不是 bitwise-or )运算符:
input = [0x6B, 0x6A, 0x6D, 0x6C]
output = []
# Iterate in pairs
for i in range(0, len(input) / 2):
# "High" nibble
hi = input[2*i] % 16; # keep 4 least significant bits
# "Low" nibble
lo = input[2*i + 1] % 16; # keep 4 least significant bits
# Multiply-by-16 is the same as shift-left-by-4
# Sum is the same as bitwise-or (if the two operands have disjointed bits)
output.append(hi * 16 + lo)
for byte in output:
print format(byte, '02x')
输出:
ba
dc
答案 3 :(得分:0)
经过反复试验:
要从0x0B
获得0x6B
,我可以做0x6B & 0x0F
。
要从0xA0
获得0x6A
,我可以做与上述相同的操作,然后再做result << 4
。
然后我可以将这些值加在一起以生成0xAB
。