Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert to big endian in ruby

I have a string in little-endian order, as a hexadecimal-encoded string

000000020597ba1f0cd423b2a3abb0259a54ee5f783077a4ad45fb6200000218
000000008348d1339e6797e2b15e9a3f2fb7da08768e99f02727e4227e02903e
43a42b31511553101a051f3c0000000000000080000000000000000000000000
0000000000000000000000000000000000000000000000000000000080020000

I'd like to byteswap each 32-bit chunk from little-endian to big-endian resulting to

020000001fba9705b223d40c25b0aba35fee549aa477307862fb45ad18020000
0000000033d14883e297679e3f9a5eb108dab72ff0998e7622e427273e90027e
312ba443105315513c1f051a0000000080000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000280

I've tried several approaches but haven't goten it to work. It'd be great if someone can show a sample implementation.

Cheers.

like image 971
user1447222 Avatar asked Apr 18 '13 08:04

user1447222


2 Answers

You can also use pack and unpack by:

  • first going decoding the hexadecimal
  • then converting to 32 bit integers in small endian
  • encoding these integers with big endian
  • encoding the result in hexadecimal.

In code:

s = "000000020597ba1f0cd4..."
[s].pack('H*').unpack('N*').pack('V*').unpack('H*')
# => "020000001fba9705b223..."
like image 106
Marc-André Lafortune Avatar answered Oct 04 '22 19:10

Marc-André Lafortune


In addition to Łukasz Niemier's answer, you can let scan handle the grouping in one step:

hex_string = "000000020597ba1f..."
hex_string.scan(/(..)(..)(..)(..)/).map(&:reverse).join
# => "020000001fba9705..."
  • scan(/(..)(..)(..)(..)/) splits the string into groups of 4 x 2 bytes:

    [["00", "00", "00", "02"], ["05", "97", "ba", "1f"], ... ]
    
  • map(&:reverse) reverses the inner 2-byte arrays:

    [["02", "00", "00", "00"], ["1f", "ba", "97", "05"], ... ]
    
  • join joins all array elements

    "020000001fba9705..."
    
like image 20
Stefan Avatar answered Oct 04 '22 19:10

Stefan