1

I'm trying to convert a binary string to a byte array of a specific format.

Sample binary data:

ê≤ÚEZêK

The hex version of the binary string looks like this:

00151b000000000190b2f20304455a000003900000004b0000

The Python script uses struct package and unpacks the above string (in binary) using this code:

data = unpack(">hBiiiiih",binarydata)

The desired byte array looks like this. This is also the output of the data array is:

(21, 27, 0, 26260210, 50611546, 912, 75, 0)

How can I unpack the same binary string using PHP's unpack() function and get the same output? That is, what's the >hBiiiiih equivalent in PHP?

So far my PHP code

$hex = "00151b000000000190b2f20304455a000003900000004b0000";
$bin = pack("H*",$hex);
print_r(unpack("x/c*"));

Which gives:

Array ( [*1] => 21 [*2] => 27 [*3] => 0 [*4] => 0 [*5] => 0 [*6] => 0 [*7] => 1 [*8] => -112 [*9] => -78 [*10] => -14 [*11] => 3 [*12] => 4 [*13] => 69 [*14] => 90 [*15] => 0 [*16] => 0 [*17] => 3 [*18] => -112 [*19] => 0 [*20] => 0 [*21] => 0 [*22] => 75 [*23] => 0 [*24] => 0 )

Would also appreciate links to a PHP tutorial on working with pack/unpack.

1 Answer 1

2

This produces the same result as does Python, but it treats signed values as unsigned because unpack() does not have format codes for signed values with endianness. Also note that the integers are converted using long, but this is OK because both have the same size.

$hex = "00151b000000000190b2f20304455a000003900000004b0000";
$bin = pack("H*", $hex);
$x = unpack("nbe_unsigned_1/Cunsigned_char/N5be_unsigned_long/nbe_unsigned_2", $bin);

print_r($x);
Array
(
    [be_unsigned_1] => 21
    [unsigned_char] => 27
    [be_unsigned_long1] => 0
    [be_unsigned_long2] => 26260210
    [be_unsigned_long3] => 50611546
    [be_unsigned_long4] => 912
    [be_unsigned_long5] => 75
    [be_unsigned_2] => 0
)

Because this data is treated as unsigned, you will need to detect whether the original data was negative, which can be done for 2 byte shorts with something similar to this:

if $x["be_unsigned_1"] >= pow(2, 15)
    $x["be_unsigned_1"] = $x["be_unsigned_1"] - pow(2, 16);

and for longs using

if $x["be_unsigned_long2"] >= pow(2, 31)
    $x["be_unsigned_long2"] = $x["be_unsigned_long2"] - pow(2, 32);
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the tip about negative numbers. Shouldn't $x["be_unsigned_long2"] be equal to $x["be_unsigned_long2"] - pow(2-32)?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.