Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re: converting artibrary binary data to numeric values

by Corion (Pope)
on Sep 30, 2012 at 18:08 UTC ( #996522=note: print w/replies, xml ) Need Help??

in reply to converting artibrary binary data to numeric values

That's exactly what unpack (and pack for the documentation) are for.

Depending on whether your sending device sends in big-endian or little-endian order, the N or V template elements look like you want them.

Also, if you have the C++ source code of the remote end, consider Struct::Binary::C, which was written for importing C structs sensibly into Perl.

Replies are listed 'Best First'.
Re^2: converting artibrary binary data to numeric values
by markle (Initiate) on Oct 01, 2012 at 19:48 UTC

    Like with unpacking from numbers it seems Perl first converts the raw binary data into a string representation of a gigantic decimal number, then it tries to unpack from that, giving bizarre results that do not correspond to the original byte order.

    Also, it seems the "b" and "B" flags to unpack expect the value to be a string of 1's and 0's, not a number.

    Please help me answer my original question. How do I convert a value which perl thinks is the scalar "\xd\xe\xa\xd\xb\xe\xe\xf" into a scalar with the numeric value 0xDEADBEEF ?

      Are you really, really sure that you get eight bytes from your file, the first having the value 0x0D and the second having the value 0x0E (and so on)?

      If so, you might need to do some bit twiddling to combine all the nibbles:

      use Data::Dumper; my $str = "\x0D\x0E\x0A\x0D\x0B\x0E\x0E\x0F"; my @bytes = unpack 'C8', $str; print Dumper \@bytes; # Now add up the byte-pairs for (0..3) { $bytes[ $_ ] = $bytes[ $_*2 ] * 16 + $bytes[ $_*2 +1 ]; }; splice @bytes, 4; # we only need the first four entries print Dumper \@bytes; my $num = unpack 'N', pack 'C4', @bytes; print sprintf "%08x (%i)", $num, $num;

      But if you get a string of four bytes, one of the two pack templates "N" or "V" will help you. See the following:

      my $str = "\xDE\xAD\xBE\xEF"; my $num = unpack 'N', $str; print sprintf "%08x (%i)", $num, $num;

      But I already told you this and you didn't show any code.

        That doesn't seem reliable because it seems like "use bytes" doesn't affect the unpack C template. It seemed like when I tried that on arbitrary data and looked at the hex dump, some results were one byte and some were three.
        I'm still not sure what you mean. The C struct has unsigned longs mostly. Each of these is 32 bytes, right? So the data should line up, each value being 32 bytes from the raw data. If I use N or V, it seems that perl first converts the raw data to a number, then unpack tries to unpack the atring representation of that number in decimal. That's not what I want. I just want the values. Convert::Binary::C did the same thing.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://996522]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2018-05-20 14:52 GMT
Find Nodes?
    Voting Booth?