http://www.perlmonks.org?node_id=996736


in reply to Re^2: converting artibrary binary data to numeric values
in thread converting artibrary binary data to numeric values

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.

Replies are listed 'Best First'.
Re^4: converting artibrary binary data to numeric values
by markle (Initiate) on Oct 01, 2012 at 21:27 UTC
    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.
Re^4: converting artibrary binary data to numeric values
by markle (Initiate) on Oct 01, 2012 at 22:08 UTC
    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.

      If you just want "the values", then keep them as strings. If that seems problematic, you have to show some code where you show how you acquire the data (say, from initializing a string), how you unpack it, and what you want to do with it in the end.

      If you want "the values" as "number", then you have to unpack them from the string. As long as you are dealing with four-byte numbers, or your Perl and the C program have the same interpretation of the long type, there will be no loss of accuracy.

      As for your questions about alignment etc., that is what Convert::Binary:C is set up to handle.

        Turns out my debug routine was the thing splitting from string representations of the decimal values. Unpack and Convert::Binary::C were working fine. Dunce cap. :-) Binary makes me woozy.
      The C struct has unsigned longs mostly. Each of these is 32 bytes, right?

      I would not bet on that. The C99 standard defines int as having the natural size suggested by the architecture of the execution environment (large enough to contain any value in the range INT_MIN to INT_MAX as defined in the header <limits.h>)., so an int needs at least 16 bits. Other integer types, including unsigned long, are definied similary. C requires a minimum range, but no fixed number of bits. The implementation may choose bit sizes as required by the machine. So most C compilers on 32 bit systems actually define int as a 32 bit number, long int is typically 32 or 64 bit. But if you run on a 36 bit architecture without a 32 bit emulation layer, int should use 36 bit, long int may use 72 bit, and long long int could use 144 bit. Things get more complicated on 64 bit systems that attempt to support 32 bit software, see http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models. Note that UNICOS defines all basic integer types as 64 bit.

      See also http://stackoverflow.com/questions/589575/size-of-int-long-etc, http://en.wikipedia.org/wiki/C_data_types.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)