unpack
Unpacks a binary string into an array of PHP values using a format of type codes.
unpack(string $format, string $string, int $offset = 0): array|false- Added in PHP 4.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$format | string | Type codes separated by slashes, each optionally followed by a repeater and a name for the resulting array key. Uses the same codes as pack(). |
$string | string | The binary string to read from. |
$offsetoptional | int= 0 | Byte 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 keyport.'C4octets'— four bytes under keysoctets1…octets4.'C4'with no name — keys1…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
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!.
<?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.
<?php
$data = "\x32\x42\x00\xa0";
var_dump(unpack('c2/n', $data));
var_dump(unpack('c2low/nhigh', $data));
Discussion