Welcome, guest | Sign In | My Account | Store | Cart

Given an unsigned number, of type 'int' or 'long', this function returns a corresponding number of the same type, with its byte order reversed. So if input = 0xABCDEF, then output = 0xEFCDAB

Python, 29 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def ReverseByteOrder(data):
    """
    Method to reverse the byte order of a given unsigned data value
    Input:
        data:   data value whose byte order needs to be swap
                data can only be as big as 4 bytes
    Output:
        revD: data value with its byte order reversed
    """
    s = "Error: Only 'unsigned' data of type 'int' or 'long' is allowed"
    if not ((type(data) == int)or(type(data) == long)):
        s1 = "Error: Invalid data type: %s" % type(data)
        print(''.join([s,'\n',s1]))
        return data
    if(data < 0):
        s2 = "Error: Data is signed. Value is less than 0"
        print(''.join([s,'\n',s2]))
        return data

    seq = ["0x"]

    while(data > 0):
        d = data & 0xFF     # extract the least significant(LS) byte
        seq.append('%02x'%d)# convert to appropriate string, append to sequence
        data >>= 8          # push next higher byte to LS position

    revD = int(''.join(seq),16)

    return revD

This type of a function is sometimes needed to work with machines with different 'endian'ness that what python supports. Its also sometimes needed to decode data coming back or to be sent to embedded microcontroller based systems.

There can be atleast a couple more ways to implment the same thing: a) using 'byteswap' method from the "array" module: It only becomes a little cumbersome to parse the data given and then create an array of that type. the array module requires a 'typecode' which varies based on the number of bytes in the data being put into the array. The array module is not as intuitive as the idea of an "array" is in itself.

b) there is a suggestion about using the 'struct' module. I am unclear on the use of the 'struct' module itself. the documentation does not show well...how things are being done with the 'struct' module. I am guessing that to do the above, we'd have to pack the given number into a struct. which will return a string. That string then needs to be cut into 2 char worth parts and put into a list. Then we'd call list.reverse(), join the list into a string, and then unpack the same using struct module again. If there's another approach by using struct, please do comment.

I still love the simplicity of my approach in the recipe above.

4 comments

S. T. 13 years, 9 months ago  # | flag

For the applications mentioned above, one should use the struct module in the standard library. Trying to reinvent the wheel is never quite so easy as it seems:

>>> hex(ReverseByteOrder(0x0123))
'0x23'

>>> ReverseByteOrder(-0x0123)
Traceback (most recent call last):
...
ValueError: invalid literal for int() with base 16: '0x23x1'
Vishal Sapre (author) 13 years, 9 months ago  # | flag

The new solution solves the first issue, as given by S.T. for the second flaw, I have not restricted the recipe name itself :)) Please do suggest better ways of doing the above using the struct module.

Vishal Sapre (author) 13 years, 9 months ago  # | flag

The new solution solves the first issue, as given by S.T. For the second flaw, I have now restricted the recipe to support unsigned numbers only itself :)) Please do suggest better ways of doing the above using the struct module.

Vishal Sapre (author) 11 years, 10 months ago  # | flag
dstr = hex(data)[2:].replace('L','')
byteCount = len(dstr[::2])
val = 0
for i,n in enumerate(range(byteCount)):
    d = data & 0xFF
    val |= (d << (8 * (byteCount - i - 1)))
    data >>= 8

# val is the byteswapped version of data
Created by Vishal Sapre on Thu, 14 Aug 2008 (MIT)
Python recipes (4591)
Vishal Sapre's recipes (2)

Required Modules

  • (none specified)

Other Information and Tasks