Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I need to extract the integers contained in a binary file. The format of the file first specifies how many bytes (1..8) are used to represent each integer (in big-endian). I then use read to get the specified bytes into a variable. But how can I unpack the bytes properly so they are interpreted as a number? I have already read through pack and perlpacktut and could only find a solution for integers of size 1, 2, 4, and 8 bytes.
  • Comment on How to unpack numbers with varying sizes?

Replies are listed 'Best First'.
Re: How to unpack numbers with varying sizes?
by Anonymous Monk on Feb 13, 2011 at 04:13 UTC
    I'm sure there's a more efficient and succinct method, but this should work:
    # my $bytes = read ... my $bitstring = unpack 'B*', $bytes; $bitstring = sprintf '%.64d', $bitstring; my $num = unpack 'Q', pack 'B*', $bitstring;
      'Q' should be 'Q>' if it's big endian.
Re: How to unpack numbers with varying sizes?
by Anonymous Monk on Feb 13, 2011 at 02:36 UTC
    and could only find a solution for integers of size 1, 2, 4, and 8 bytes

    Why is that a problem? Maybe youwant Math::BigInt?

      Because the data includes numbers encoded in 3, 5, 6, and 7 bytes as well.

        unpack doesn't support those sizes directly. You could extract them in parts, then assemble them.

        # 3-bytes, network order my ($o1, $o2, $o3) = unpack('CCC', $_); my $n = ($o1 << 16) | ($o2 << 8) | $o3; -or- my ($n1, $n2) = unpack('Cn', $_); my $n = ($n1 << 16) | $n2;

        Alternatively, you could add padding.

        # 3-bytes, network order my $n = unpack('N', "\x00".$_);
        Because the data includes numbers encoded in 3, 5, 6, and 7 bytes as well.

        And why do you think that is a problem? a 3 byte integer fits into a 4 byte, or 8 byte integer without problems