2

I have a binary string where the bytes are reversed in the following way: The file contains e.g the four bytes 0x18 0xb1 0x35 0x41 and should be interpreted as 0xb1 0x18 0x41 0x35 into my perl string or array. That is, every pair of bytes is reversed.

How can I use unpack to unpack this format?

I also wonder if this kind of packing/format is standard, does it have a name? I apologise if I'm using the wrong terms, I'm not used to byte-level manipulation.

ikegami
  • 367,544
  • 15
  • 269
  • 518
Anna
  • 2,645
  • 5
  • 25
  • 34
  • 1
    This is called little endian. – tkausl Oct 24 '21 at 22:08
  • @tkausl I had only heard little/big endian used in reference to bit order, not byte order? – Anna Oct 24 '21 at 22:09
  • 2
    Little endian and big endian always applies to bytes, not bits. There's no way to address bits, so the concept makes no sense for bits. – ikegami Oct 25 '21 at 03:09
  • @ikegami thank you for clarifying and for you great answer! I checked the wikipedia page and found this, so I think it was my telecom and mcu experience hindering my learning :) "Endianness may also be used to describe the order in which the bits are transmitted over a communication channel, e.g., big-endian in a communications channel transmits the most significant bits first. Bit-endianness is seldom used in other contexts." – Anna Oct 25 '21 at 09:56

2 Answers2

4

So you have "\x18\xb1\x35\x41..." and you want "\xb1\x18\x41\x35..."

$s =~ s/(.)(.)/$2$1/sg;
my $out = $in =~ s/(.)(.)/$2$1/srg;
my $out = pack "n*", unpack "v*", $in;
my $out = pack "C*", unpack "(xCXXCx)*", $in;

... or an array containing 0xb1, 0x18, 0x41, 0x35, ....

my @out = unpack "C*", $in =~ s/(.)(.)/$2$1/srg;
my @out = unpack "C*", pack "n*", unpack "v*", $in;
my @out = map { $_ >> 8, $_ & 0xFF } unpack "v*", $in;
my @out = unpack "(xCXXCx)*", $in;
ikegami
  • 367,544
  • 15
  • 269
  • 518
1

This worked for me:

unpack( 'SS', $bytes );
Anna
  • 2,645
  • 5
  • 25
  • 34
  • 1
    This depends on the computer you are running the code on. For example, if your machine is using an Intel processor, `S` will use [little endian](https://en.wikipedia.org/wiki/Endianness) interpretation, on the other hand on a Cray it will use big endian, see [perldoc pack](https://perldoc.perl.org/functions/pack). You can force little endian interpretation by using `S – Håkon Hægland Oct 25 '21 at 01:39