10

我想在 python 中构建一个小型格式化程序,将嵌入在十六进制字符串行中的数值返回给我。

它是我的格式化程序的核心部分,格式化超过 100 行/秒(每行约 100 个字符)应该相当快。

下面的代码应该给出一个我目前被阻止的例子。

'data_string_in_orig' 显示给定的输入格式。它必须为每个字进行字节交换。需要从 'data_string_in_orig' 到 'data_string_in_swapped' 的交换。最后我需要如图所示的结构访问。预期结果在评论中。

在此先感谢 Wolfgang R

#!/usr/bin/python

import binascii
import struct

## 'uint32 double'
data_string_in_orig    = 'b62e000052e366667a66408d'
data_string_in_swapped = '2eb60000e3526666667a8d40'
print data_string_in_orig

packed_data = binascii.unhexlify(data_string_in_swapped)
s = struct.Struct('<Id')
unpacked_data = s.unpack_from(packed_data, 0)  
print 'Unpacked Values:', unpacked_data

## Unpacked Values: (46638, 943.29999999943209)

exit(0)
4

4 回答 4

16

array.arrays有一个字节交换方法

import binascii
import struct
import array
x = binascii.unhexlify('b62e000052e366667a66408d')
y = array.array('h', x)  
y.byteswap()
s = struct.Struct('<Id')
print(s.unpack_from(y))

# (46638, 943.2999999994321)

之所以选择hinarray.array('h', x)是因为它告诉array.array我们将数据 inx视为一个 2 字节短数组。重要的是每个项目都被视为 2 字节长。H,表示 2 字节无符号短,同样有效。

于 2012-10-31T10:25:32.457 回答
10

这应该完全符合 unutbu 的版本,但对于某些人来说可能更容易遵循......

from binascii import unhexlify
from struct import pack, unpack
orig = unhexlify('b62e000052e366667a66408d')
swapped = pack('<6h', *unpack('>6h', orig))
print unpack('<Id', swapped)

# (46638, 943.2999999994321)

基本上,解压 6 个 short-endian,重新打包为 6 个 short-endian。

同样,与 unutbu 的代码相同,您应该使用他的。

编辑刚刚意识到我可以为此使用我最喜欢的 Python 习语......也不要这样做:

orig = 'b62e000052e366667a66408d'
swap =''.join(sum([(c,d,a,b) for a,b,c,d in zip(*[iter(orig)]*4)], ()))
# '2eb60000e3526666667a8d40'
于 2012-10-31T10:43:51.380 回答
1

从 'data_string_in_orig' 到 'data_string_in_swapped' 的交换也可以在不使用任何导入的情况下通过推导完成:

>>> d = 'b62e000052e366667a66408d'
>>> "".join([m[2:4]+m[0:2] for m in [d[i:i+4] for i in range(0,len(d),4)]])
'2eb60000e3526666667a8d40'

理解适用于在表示 16 位字的十六进制字符串中交换字节顺序。为不同的字长修改它是微不足道的。我们也可以制作一个通用的十六进制数字顺序交换功能:

def swap_order(d, wsz=4, gsz=2 ):
    return "".join(["".join([m[i:i+gsz] for i in range(wsz-gsz,-gsz,-gsz)]) for m in [d[i:i+wsz] for i in range(0,len(d),wsz)]])

输入参数是:

d : 输入的十六进制字符串

wsz:以半字节为单位的字长(例如,对于 16 位字 wsz=4,对于 32 位字 wsz=8)

gsz:保持在一起的半字节数(例如,重新排序字节 gsz=2,重新排序 16 位字 gsz = 4)

于 2016-04-20T12:55:09.453 回答
0
import binascii, tkinter, array
from tkinter import *

infile_read = filedialog.askopenfilename()

with open(infile, 'rb') as infile_:
    infile_read = infile_.read()

x = (infile_read)
y = array.array('l', x)
y.byteswap()
swapped = (binascii.hexlify(y))

这是一个 32 位无符号短交换,我用与“unutbu”的答案非常相似的代码实现了,只是更容易理解。从技术上讲,交换不需要 binascii。只需要 array.byteswap。

于 2015-05-04T13:38:18.733 回答