reorder byte order in hex string (python)

后端 未结 4 981
再見小時候
再見小時候 2021-01-05 05:17

I want to build a small formatter in python giving me back the numeric values embedded in lines of hex strings.

It is a central part of my formatter and should be re

相关标签:
4条回答
  • 2021-01-05 05:58
    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))
    

    This is a 32 bit unsigned short swap i achieved with code very much the same as "unutbu's" answer just a little bit easier to understand. And technically binascii is not needed for the swap. Only array.byteswap is needed.

    0 讨论(0)
  • 2021-01-05 06:02

    array.arrays have a byteswap method:

    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)
    

    The h in array.array('h', x) was chosen because it tells array.array to regard the data in x as an array of 2-byte shorts. The important thing is that each item be regarded as being 2-bytes long. H, which signifies 2-byte unsigned short, works just as well.

    0 讨论(0)
  • 2021-01-05 06:02

    This should do exactly what unutbu's version does, but might be slightly easier to follow for some...

    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)
    

    Basically, unpack 6 shorts big-endian, repack as 6 shorts little-endian.

    Again, same thing that unutbu's code does, and you should use his.

    edit Just realized I get to use my favorite Python idiom for this... Don't do this either:

    orig = 'b62e000052e366667a66408d'
    swap =''.join(sum([(c,d,a,b) for a,b,c,d in zip(*[iter(orig)]*4)], ()))
    # '2eb60000e3526666667a8d40'
    
    0 讨论(0)
  • 2021-01-05 06:02

    The swap from 'data_string_in_orig' to 'data_string_in_swapped' may also be done with comprehensions without using any imports:

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

    The comprehension works for swapping byte order in hex strings representing 16-bit words. Modifying it for a different word-length is trivial. We can make a general hex digit order swap function also:

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

    The input params are:

    d : the input hex string

    wsz: the word-size in nibbles (e.g for 16-bit words wsz=4, for 32-bit words wsz=8)

    gsz: the number of nibbles which stay together (e.g for reordering bytes gsz=2, for reordering 16-bit words gsz = 4)

    0 讨论(0)
提交回复
热议问题