sfactor
sfactor

Reputation: 13072

Perl, Decoding bits stored in a binary file

I'm decoding a fixed-width binary file in perl. One of the fields is 1 byte in length and the 8 bits are encoded such that:

The 7th Bit unused, The 0-4th bit is used to indicate Field1. The 5-6th Bit is used to indicate Field2.

For example the field 0x27 will give Field1 = 7, Field2 = 1.

I'm reading all the fields into a hash table called raw{} and then decoding the values into another hash called processed{}.

The code (only shown for this one byte) is

while (read(FILE, $buff, 559)) {
  %raw = ();            # Hash for first-pass extractions
  %processed = ();      # Hash for cleaned up values, for output

  (
    ......
    $raw{'Field12'},
    ......
  )= unpack('
             .....
             H2
             .....
             h*',$buff);

$prcoessed{'Field1'} = unpack("B8", pack("H8", $raw{'Field12'})) & 0x1f;
$prcoessed{'Field2'} = (unpack("B8", pack("H8", $raw{'Field12'})) >> 5) & 0x3;

However, I don't get the desired values. I get $prcoessed{'Field1'} = 15 and $prcoessed{'Field2'} = 3. Where am I going wrong?

Upvotes: 0

Views: 97

Answers (1)

choroba
choroba

Reputation: 242443

0x1f is a number, you need to transform it into a character.

Instead of packs and unpacks, you can use ord and chr:

#!/usr/bin/perl
use warnings;
use strict;

my $char = chr 0x27;

my $field1 = $char & chr 0x1f;

my $field2 = $char & chr 0x60;
$field2 = chr(ord($field2) >> 5);

print ord, "\n" for $field1, $field2;

The same script using pack and unpack:

my $char = pack 'C', 0x27;

my $field1 = $char & pack 'C', 0x1f;

my $field2 = $char & pack 'C', 0x60;
$field2 = pack 'C', unpack('C', $field2) >> 5;

print unpack('C', $_), "\n" for $field1, $field2;

Upvotes: 1

Related Questions