如何在不进行字符串操作的情况下清除/修复这些字节?

时间:2018-11-27 11:51:37

标签: python

我有一个bytearray,例如[0x6B, 0x6A, 0x6D, 0x6C]

出于无法控制的原因,字节“不正确”,需要修复。我想要的输出是像bytearray这样的[0xAB, 0xCD]

因此,在我的示例中,我想忽略字节的“ 6”部分。 (6仅是示例,它可以更改)。

我目前正在通过以下方式这样做:

  1. 遍历字节对
  2. 将字节转换为十六进制字符串,例如'6B6A'
  3. 采用字符串的第4个和第2个字符来构建'AB'
  4. 'AB'十六进制字符串转换为字节

我已经有一个可行的解决方案,但是使用带有数字值的字符串操作感觉很“错误”。

我不擅长按位运算符,也不确定是否可以使用按位运算符或完全其他方式来以更快和/或更有效的方式执行此操作。

4 个答案:

答案 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