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

I am trying to write characters to a file using their binary equivalents. To do this I am using pack:
$bob=pack("B*",11101100); print DATAFILE $bob;
Then I read the data back from the file and unpack it thus:
$bobagain=unpack("B*",$stufffromfile); $bobunpacked=unpack("B*",$bob); print $bobagain; print "\n$bobunpacked";
And they are equal, yes! So I then tried to write two bytes (which should be two characters in ASCII, or perhaps one if you use a unicode interpretation (which I eventually will)).
$bob = pack("B*",1110110010010000); print DATAFILE $bob;
and then did the same thing:
$bobagain=unpack("B*",$stufffromfile); $bobunpacked=unpack("B*",$bob); print $bobagain; print "\n$bobunpacked";
But they are not equal!
from file: 111000111000010010000111 from $bobunpacked: 101101100100111110000000
and $bobunpacked isn't even what it should be! what is going on? I have absolutely no clue what is going on, can anyone help me with this?

Replies are listed 'Best First'.
(tye)Re: Problems using pack
by tye (Sage) on Aug 19, 2002 at 05:11 UTC

    Try this:

    $ perl -e "print 1110110010­010000" 1.11011001001e+015
    You are entering a very big number (in base 10, no less). You need to put quotes around those long strings of ones and zeros. Your code is doing the same thing as:     $bob = pack("B*","1.11011001001e+015") where "." (byte 46, even) is the same as "0" while "e" and "+" (bytes 101 and 43, both odd) are the same as "1".

    Though I'm not sure why you get what you report for $bobupacked (in part because you don't show enough of that part of the code).

            - tye (but my friends call me "Tye")
Re: Problems using pack
by spurperl (Priest) on Aug 19, 2002 at 05:29 UTC
    If you pack a string into a variable and then unpack it, it must be equal, and that has nothing to do with writing to a file. Try this:
    $g = "0110110001101101"; $bob = pack("B*", $g); print $g . "\n"; print unpack("B*", $bob);
    You should get the same results. Now, try a file (remove the -l option of perl, as it inserts a new line):
    open(FH, ">fh"); $g = "0110110001101101"; $bob = pack("B*", $g); print FH $bob; close(FH); open(FH, "fh"); read(FH, $from_file, 2); print $g . "\n"; print unpack("B*", $from_file), "\n";
    And report the results (note, I changed the bytes to be visible, now it should print "lm")
      You are correct, they must be equal. I tried your code and it worked wonderfully. The error in what I did is that the long decimal numbers I was using must be in quotes otherwise, as tye said, they would be interrpeted as 1.101100011e12 which is not what I wanted. Sticking it in a variable such as $g and then using
      $bob = pack("B*",$g);
      does the trick. Thanks everyone for helping with this!
Re: Problems using pack
by JupiterCrash (Monk) on Aug 19, 2002 at 03:32 UTC
    If you're on Unix, this will have no effect, but on Windows, maybe this is the problem... ?

    After opening DATAFILE but before writing any data, try a 'binmode(DATAFILE); ' to make sure it's treated as a binary file.
Re: Problems using pack
by BrowserUk (Patriarch) on Aug 19, 2002 at 08:53 UTC

    WARNING What follows WILL NOT SOLVE YOUR ORIGINAL PROBLEM! To understand this, scan to the second WARNING! close to the bottom.

    Also, whilst all the code and the output below are live output from one of my test sessions with some (where some equals lots:) of my failed attempts to understand Unicode omitted. Every single line is real code and real output, but that doesn't mean all the conclusion I draw or the assumptions I make are correct. Only that they fit my observations using limited test data!

    Tanaka as tye already mentioned, pack( 'B*', 1110110010010000 ) is packing large decimal number.

    What noone has mentioned yet (as I'm writing, by the time I post it maybe different:), is that, if you really want to pack an ascii encoded binary string into bytes, you need to use quotes around it.