如何将十六进制数组转换为bytes-python数组

时间:2018-04-19 17:01:20

标签: python

我在python中有一个十六进制值数组,我想把它转换成那些分成单个字节的值的数组,存储为字符串。

例如:

给出输入

hexValueAr = [0x085F80, 0x0109A53, 0x0188C6D]

我想输出

bytesAr = ['08', '5F', '80', ...]

我想知道是否有内置的python函数来执行此转换,或者其他一些简单的方法吗?

编辑:我的输入值是在数组中以十六进制值存储的整数。我的输入数组有48个这样的整数,我只是缩短它以便于阅读。希望这会有所帮助。

4 个答案:

答案 0 :(得分:1)

def int_to_hexbytes(i):
    s = '%X' % i
    if len(s) % 2:
        s = '0' + s
    return [s[i:i+2] for i in range(0, len(s), 2)]

def words_to_hexbytes(a):
    ret = []
    for i in a:
        ret += int_to_hexbytes(i)
    return ret

assert int_to_hexbytes(0x0123456789ABCDEF) == ['01', '23', '45', '67', '89', 'AB', 'CD', 'EF']
assert int_to_hexbytes(0x123456789ABCDEF0) == ['12', '34', '56', '78', '9A', 'BC', 'DE', 'F0']

assert words_to_hexbytes([0x123, 0x456, 0x78]) == ['01', '23', '04', '56', '78']
assert words_to_hexbytes([0x085F80, 0x0109A53, 0x0188C6D]) == ['08', '5F', '80', '10', '9A', '53', '18', '8C', '6D']

int_to_hexbytes使用%格式化运算符将整数参数转换为包含其十六进制表示形式的字符串;然后使用列表推导将该字符串每隔一个字符(即每个字节)分成一个列表。请注意,由于最左边的字节可能低于0x10,因此代码会事先预先设置'0'(即当字符串为奇数长度时)。

words_to_hexbytes只需遍历数组参数并附加int_to_hexbytes的结果。

之后assert只是测试代码的快捷方式,同时向读者展示预期结果。

答案 1 :(得分:1)

您的整数以十六进制编码的事实与问题无关。

hexValueAr = [0x085F80, 0x0109A53, 0x0188C6D]

hexValueAr = [548736, 1088083, 1608813]

产生相同的列表。

Python整数有一种方法可以转换为字节:int.to_bytes。之后转换为字符串非常简单(只需使用str.formathex)。唯一的问题是您需要知道预先使用的字节数。在您的情况下,您可以使用数字3,也可以使用方法int.bit_length来计算它。

以下是上述一种可能的实现方式:

from math import ceil

bytesAr = []
for num in hexValueAr:
    count = ceil(num.bit_length() / 8)
    bytes = num.to_bytes(count, 'big')
    bytesAr.extend('{:02X}'.format(x) for x in bytes)

这会产生结果

['08', '5F', '80', '10', '9A', '53', '18', '8C', '6D']

这里的顺序是big-endian:整数的最高字节位于数组的最低索引中。

如果你想把它作为一个单行,你可以这样做:

bytesAr = ['{:02X}'.format(x) for num in hexValueAr for x in num.to_bytes(ceil(num.bit_length() / 8), 'big')]

这里可能需要注意的是输入中的不同数字可能会在输出中为您提供不同数量的元素。例如,如果输入为[0x00AB, 0x109C],则第一个元素将产生一个字符串,而第二个元素将产生2.如果要避免这种情况,请查找编码其中一个整数所需的最大字节数,并使用它而不是ceil(num.bit_length() / 8)

byte_count = ceil(max(hexValueAr).bit_length() /  8))
bytesAr = ['{:02X}'.format(x) for num in hexValueAr for x in num.to_bytes(byte_count, 'big')]

在这种情况下,像[0x00AB, 0x109C]这样的输入会产生一堆零,但每个数字的字节数相等:['00', ''AB', '10', '9C']

答案 2 :(得分:-2)

hexValueAr=['0x085F80','0x0109A53','0x0188C6D']

stripped = list(map(lambda x: x.split('x')[1], hexValueAr))
byte_list = []

for hex_string in stripped:
     for i in range(3):
         byte_list += [hex_string[2*i:2*i+2]]

print(byte_list)

答案 3 :(得分:-2)

hexValueAr=[0x085F80,0x0109A53,0x0188C6D]
bytes = []
for i in hexValueAr:
    x = "%6.6x" % i
    bytes += [x[0:2], x[2:4], x[4:6]]