Patrick B.
Patrick B.

Reputation: 12363

How to byte-swap a 32-bit integer in python?

Take this example:

i = 0x12345678
print("{:08x}".format(i))
   # shows 12345678
i = swap32(i)
print("{:08x}".format(i))
   # should print 78563412

What would be the swap32-function()? Is there a way to byte-swap an int in python, ideally with built-in tools?

Upvotes: 31

Views: 75400

Answers (5)

noodle7
noodle7

Reputation: 61

The array module provides a byteswap() method for fixed sized items. The array module appears to be in versions back to Python 2.7

array.byteswap() “Byteswap” all items of the array. This is only supported for values which are 1, 2, 4, or 8 bytes in size;

Along with the fromfile() and tofile() methods, this module is quite easy to use:

import array

# Open a data file.
input_file = open( 'my_data_file.bin' , 'rb' )

# Create an empty array of unsigned 4-byte integers.
all_data = array.array( 'L' )

# Read all the data from the file.
all_data.fromfile( input_file , 16000 )               # assumes the size of the file

# Swap the bytes in all the data items.
all_data.byteswap( )

# Write all the data to a new file.
output_file = open( filename[:-4] + '.new' , 'wb' )    # assumes a three letter extension
all_data.tofile( output_file )

# Close the files.
input_file.close( )
output_file_close( )

The above code worked for me since I have fixed-size data files. There are more Pythonic ways to handle variable length files.

Upvotes: 3

RobD
RobD

Reputation: 105

Maybe simpler use the socket library.

from socket import htonl

swapped = htonl (i)
print (hex(swapped))

that's it. this library also works in the other direction with ntohl

Upvotes: 3

Carsten
Carsten

Reputation: 18446

One method is to use the struct module:

def swap32(i):
    return struct.unpack("<I", struct.pack(">I", i))[0]

First you pack your integer into a binary format using one endianness, then you unpack it using the other (it doesn't even matter which combination you use, since all you want to do is swap endianness).

Upvotes: 35

Artem Zankovich
Artem Zankovich

Reputation: 2349

From python 3.2 you can define function swap32() as the following:

def swap32(x):
    return int.from_bytes(x.to_bytes(4, byteorder='little'), byteorder='big', signed=False)

It uses array of bytes to represent the value and reverses order of bytes by changing endianness during conversion back to integer.

Upvotes: 19

nos
nos

Reputation: 229148

Big endian means the layout of a 32 bit int has the most significant byte first,

e.g. 0x12345678 has the memory layout

msb             lsb
+------------------+
| 12 | 34 | 56 | 78|
+------------------+

while on little endian, the memory layout is

lsb             msb
+------------------+
| 78 | 56 | 34 | 12|
+------------------+

So you can just convert between them with some bit masking and shifting:

def swap32(x):
    return (((x << 24) & 0xFF000000) |
            ((x <<  8) & 0x00FF0000) |
            ((x >>  8) & 0x0000FF00) |
            ((x >> 24) & 0x000000FF))

Upvotes: 31

Related Questions