unpack

Unpacks a binary string into an array of PHP values using a format of type codes.

Signature
unpack(string $format, string $string, int $offset = 0): array|false
  • Added in PHP 4.0

Parameters

ParameterTypeDescription
$formatstringType codes separated by slashes, each optionally followed by a repeater and a name for the resulting array key. Uses the same codes as pack().
$stringstringThe binary string to read from.
$offsetoptionalint= 0Byte offset at which to start reading.

Return value

array|falseAn associative array of unpacked values, or false on failure.

Errors

Throws ValueError for an unknown format code, an invalid repeater, or an offset outside the input string.

Changelog

  • PHP 7.2.0float and double codes gained explicit big-endian and little-endian support.
  • PHP 7.1.0The offset parameter was added.

unpack() is the reverse of pack(): give it bytes and a layout, get back an array. The format differs from pack()'s in one important way — fields are separated by / and each one may carry a name that becomes the array key.

Naming the fields

  • 'nport' — one 16-bit big-endian value under the key port.
  • 'C4octets' — four bytes under keys octets1 … octets4.
  • 'C4' with no name — keys 1…4.

What trips people up

Leaving names off more than one field is the classic bug: numbering restarts at 1 for every unnamed group, so later fields silently overwrite earlier ones and you get fewer entries than you expected. Name every field.

Second, PHP integers are signed. A 64-bit unsigned value above PHP_INT_MAX comes back negative; read it as a string or use GMP if that matters. Third, a format that asks for more bytes than the string holds is an error rather than a short read, so validate strlen() first, and use the offset parameter instead of substr() when walking through a buffer field by field.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Reading a fixed binary header (magic number, version, length) from a file you just read into a string.
  • Decoding a 4-byte big-endian length prefix before reading the payload of a socket message.
  • Turning a packed IP address or GUID from a database BINARY column back into readable numbers.

Frequently asked questions

Why does unpack return fewer values than my format has?

Unnamed format groups restart their numeric keys at 1, so a later group overwrites an earlier one. Give each field a name in the format string.

Why is my unpacked 64-bit number negative?

PHP integers are signed, so unsigned values above PHP_INT_MAX wrap to negative. Read such fields as two 32-bit halves or use GMP/bcmath if the full range is needed.

How do I read from the middle of a binary string?

Pass the byte position as the third argument, available since PHP 7.1: unpack('Nlen', $data, 8). It is faster and clearer than slicing with substr().

More examples

Reading a header with an offset

The first call reads the 6-byte header, then offset 6 skips straight to the payload without copying the string with substr(), printing length 1024, port 8080 and text HELLO!.

Example · php
<?php
$message = pack('NnA6', 1024, 8080, 'HELLO!');

$header = unpack('Nlength/nport', $message);
print_r($header);

$body = unpack('A6text', $message, 6);
print_r($body);

Unnamed fields overwrite each other

The unnamed version returns only two entries because the n field reuses key 1, while the named version returns low1, low2 and high with all three values intact.

Example · php
<?php
$data = "\x32\x42\x00\xa0";

var_dump(unpack('c2/n', $data));
var_dump(unpack('c2low/nhigh', $data));

Discussion

  • Be the first to comment on this lesson.