Re: [SLUG] PHP Question: strings and numbers

From: Paul M Foster (paulf@quillandmouse.com)
Date: Fri Aug 26 2005 - 10:46:21 EDT


On Fri, Aug 26, 2005 at 12:52:17AM -0400, Ian C. Blenke wrote:

> Paul M Foster wrote:
>
> >Anyone know how to pull data out of a file and interpret it as binary in
> >PHP? Specifically, I have four bytes in a file whose contents I want to
> >bit-shift left by varying amounts, and then store the results as a
> >number. The raw data is binary. In python, it looks like this:
> >
> >s0 = ord(four_byte_string[0])
> >s1 = ord(four_byte_string[1])
> >s2 = ord(four_byte_string[2])
> >s3 = ord(four_byte_string[3])
> >return (s3 << 24) | (s2 << 16) | (s1 << 8) | s0
> >
> >and the value returned should be a number. Anyone know how to accomplish
> >a similar thing in PHP?
> >
> >
> Depending on the binary endianness, you could always just fread() in the
> 4 bytes into a string and settype() it to an integer (or do a "+= 0" to
> convert it).
>
> If you read in each byte, a character at a time, you can always use
> pack() to ensure the endianness.
>
> This is the kind of thing pack() and unpack() are for (vaguely similar
> to the perl equivalent functions):
>
> $handle = fopen("/some/path/binary_file.bin", "rb");
> $s0 = fread($handle, 1);
> $s1 = fread($handle, 1);
> $s2 = fread($handle, 1);
> $s3 = fread($handle, 1);
> $binary_string = pack ('C4', $s0, $s1, $s2, $s3);
>
> // This is just an example of how to use unpack()
> $value=unpack('Linteger',$binary_string);
> $integer=$value['integer'];
> $integer+=0; // $integer is now a number containing the unpacked
> Long (32bit) value parsed from $binary_string
>
> // Alternatively, $binary_string is already a 32bit integer, just
> make sure php treats it as a number. This _should_ work.
> $binary_string+=0;
>
> fclose($handle);
>
> I think this is correct, but I've not written php in a while, and the
> the above was pasted together off of some google searches without
> testing any of it.

I actually found this before you emailed the list, but congratulations
for being the guy who could answer the question.

The solution actually looks like this:

$header = fread($fd, 12);
$hd = unpack('Vjunk/Vnrecs/vhlen/vrlen', $header);
extract($hd);

which yields $junk, $nrecs, $hlen and $rlen as numeric variables. The
'V' (or 'v') versus the 'N' (or 'n') in unpack allows you to simply
control endianness. It also yields $hd[junk], $hd[nrecs], etc. There's
no need to use pack() first, since the assumption is that the data is
already packed.

Unfortunately, the documentation for unpack() seems to indicate you can
use unpack('V/V/v/v', $header), but it apparently doesn't work without
actually giving a variable name after each conversion spec.

Anyway, thanks for the assist.

Paul

-----------------------------------------------------------------------
This list is provided as an unmoderated internet service by Networked
Knowledge Systems (NKS). Views and opinions expressed in messages
posted are those of the author and do not necessarily reflect the
official policy or position of NKS or any of its employees.



This archive was generated by hypermail 2.1.3 : Fri Aug 01 2014 - 20:33:20 EDT