假设我有一个很大的十六进制数字0x1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF
我想轻松地从这个十六进制数中获取10-20字节,我该怎么做呢?我知道我可以将数据右移10 * 8次,但剩余的十六进制数字仍然是有效字节。
答案 0 :(得分:0)
最简单的方法是使用字符串切片。由于最低字节在最右边,最高字节在左边,因此我们可以利用负索引。
def sub_bytes(i, start=0, end=0):
i_str = hex(i)[2:] # skip 0x part
i_sub = i_str[-end * 2: len(i_str) - start * 2] # get the bytes we need
return int(i_sub or '0', 16) # convert to back int
len(i_str)
在这里,用于更好的start = 0处理
让我们尝试您的价值
In [2]: value = 0x1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF
In [3]: sub_bytes(value, 0, 3)
Out[3]: 11259375
In [4]: hex(sub_bytes(value, 0, 3))
Out[4]: '0xabcdef'
In [6]: hex(sub_bytes(value, 10, 20))
Out[6]: '0x90abcdef1234567890ab'
In [7]: hex(sub_bytes(value, 45))
Out[7]: '0x123456'
如果请求的切片为空或超出范围,我在这里返回0x0,但是如果愿意,您可以提高IndexError
。
更新
在Python 3.2+中,int
上定义了to_bytes
和from_bytes
,在这种情况下更高效,更方便
import math
def slice_bytes(value, a=None, b=None, byteorder='little'):
size = math.ceil(value.bit_length() / 8)
value_bytes = value.to_bytes(size, byteorder)
return int.from_bytes(value_bytes[a: b], byteorder)
在对具有288998字节的数字7 ** 7 ** 7
进行了性能测试之后,我发现slice_bytes
比Karl的直接方法要快。 sub_bytes
显然要慢一些。
答案 1 :(得分:0)
我觉得位掩码方法不是弄乱字符串和子字符串,而是一种更直接的方法来获取所需的位。在您的评论中,您提到位掩码非常大,这是事实,但这对程序而言不是问题。
我有一个示例函数,可以根据要从数据中获取多少个字节为您制作掩码。然后,您只需AND
使用具有右移值的掩码即可获得所需的值。
假设您要从字节索引2开始获取4个字节的数据。
def get_bytes(value, start, amount):
shifted_value = value >> (start * 8) # Multiply by 8 for how much to right shift
mask = make_mask(amount)
return shifted_value & mask
def make_mask(byte_amount):
if byte_amount > 0:
bin_string = '1' * (byte_amount * 8) # Create binary string mask
else:
bin_string = '0' # Make result 0
return int(bin_string, 2) # Return integer representation
value = 0x1234567890ABCDEF1234567890ABCDEF
result = get_bytes(value, 2, 4)
结果最终为十进制整数1450741931
,转换为十六进制的0x567890ab
。