reordenar orden de bytes en cadena hexadecimal (python)

Quiero construir un pequeño formateador en python que me devuelva los valores numéricos incrustados en líneas de cadenas hexadecimales.

Es una parte central de mi formateador y debería ser razonablemente rápido para formatear más de 100 líneas / seg (cada línea tiene unos ~ 100 caracteres).

El siguiente código debería dar un ejemplo donde actualmente estoy bloqueado.

‘data_string_in_orig’ muestra el formato de entrada dado. Tiene que ser byte intercambiado por cada palabra. Se necesita el cambio de ‘data_string_in_orig’ a ​​’data_string_in_swapped’. Al final necesito el acceso a la estructura como se muestra. El resultado esperado está dentro del comentario.

Gracias de antemano 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) 

    array.arrays tiene un método byteswap :

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

    La h en array.array('h', x) se eligió porque le dice a array.array que considere los datos en x como una matriz de cortocircuitos de 2 bytes. Lo importante es que cada elemento se considere de 2 bytes de longitud. H , que significa corto de 2 bytes sin firmar, funciona igual de bien.

    Esto debería hacer exactamente lo que hace la versión de unutbu, pero podría ser un poco más fácil de seguir para algunos …

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

    Básicamente, desempaquetar 6 shorts big-endian, repackear como 6 shorts little-endian.

    De nuevo, lo mismo que hace el código de Unutbu, y debes usar el suyo.

    edit Acabo de darme cuenta de que utilizo mi idioma Python favorito para esto ... No hagas esto tampoco:

     orig = 'b62e000052e366667a66408d' swap =''.join(sum([(c,d,a,b) for a,b,c,d in zip(*[iter(orig)]*4)], ())) # '2eb60000e3526666667a8d40' 
     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)) 

    Este es un intercambio corto sin firma de 32 bits que obtuve con el código muy parecido a la respuesta de “unutbu”, un poco más fácil de entender. Y técnicamente no se necesita binascii para el canje. Sólo se necesita array.byteswap.

    El intercambio de ‘data_string_in_orig’ a ​​’data_string_in_swapped’ también se puede hacer con comprensiones sin usar ninguna importación:

     >>> 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' 

    La comprensión funciona para intercambiar el orden de bytes en cadenas hexadecimales que representan palabras de 16 bits. Modificarlo para una longitud de palabra diferente es trivial. También podemos hacer una función de intercambio de orden de dígitos hexadecimales general:

     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)]]) 

    Los parámetros de entrada son:

    d: la cadena hexadecimal de entrada

    wsz: el tamaño de palabra en nibbles (por ejemplo, para palabras de 16 bits wsz = 4, para palabras de 32 bits wsz = 8)

    gsz: el número de nibbles que permanecen juntos (por ejemplo, para reordenar bytes gsz = 2, para reordenar palabras de 16 bits gsz = 4)