# 1.13. Storing Binary Data in Strings

## Problem

You want to parse a string that contains values encoded as a binary structure or encode values into a string. For example, you want to store numbers in their binary representation instead of as sequences of ASCII characters.

## Solution

Use `pack( )` to store binary data in a string:

`\$packed = pack('S4',1974,106,28225,32725);`

Use `unpack( )` to extract binary data from a string:

`\$nums = unpack('S4',\$packed);`

## Discussion

The first argument to `pack( )` is a format string that describes how to encode the data that’s passed in the rest of the arguments. The format string `S4` tells `pack( )` to produce four unsigned short 16-bit numbers in machine byte order from its input data. Given 1974, 106, 28225, and 32725 as input, this returns eight bytes: 182, 7, 106, 0, 65, 110, 213, and 127. Each two-byte pair corresponds to one of the input numbers: 7 * 256 + 182 is 1974; 0 * 256 + 106 is 106; 110 * 256 + 65 = 28225; 127 * 256 + 213 = 32725.

The first argument to `unpack( )` is also a format string, and the second argument is the data to decode. Passing a format string of `S4`, the eight-byte sequence that `pack( )` produced returns a four-element array of the original numbers:

```print_r(\$nums);
Array
(
[1] => 1974
[2] => 106
[3] => 28225
[4] => 32725
)```

In `unpack( )`, format characters and their count can be followed by a string to be used as an array key. For example:

```\$nums = unpack('S4num',\$packed);
print_r(\$nums);
Array
(
[num1] => 1974
[num2] => 106
[num3] => 28225
[num4] => 32725
)```

Multiple format characters must be separated with `/` in `unpack( )`:

```\$nums = unpack('S1a/S1b/S1c/S1d',\$packed);
print_r(\$nums);
Array
(
[a] => 1974
[b] => 106
[c] => 28225
[d] => 32725
)```

The format characters that can be used with `pack( )` and `unpack( )` are listed in Table 1-2.

Table 1-2. Format characters for pack( ) and unpack( )

Format character

Data type

`a`

`A`

`h`

Hex string, low nibble first

`H`

Hex string, high nibble first

`c`

`signed char`

`C`

`unsigned char`

`s`

`signed short` (16 bit, machine byte order)

`S`

`unsigned short` (16 bit, machine byte order)

`n`

`unsigned short` (16 bit, big endian byte order)

`v`

`unsigned short` (16 bit, little endian byte order)

`i`

`signed int` (machine-dependent size and byte order)

`I`

`unsigned int` (machine-dependent size and byte order)

`l`

`signed long` (32 bit, machine byte order)

`L`

`unsigned long` (32 bit, machine byte order)

`N`

`unsigned long` (32 bit, big endian byte order)

`V`

`unsigned long` (32 bit, little endian byte order)

`f`

`float` (machine dependent size and representation)

`d`

`double` (machine dependent size and representation)

`x`

NUL byte

`X`

Back up one byte

`@`

NUL-fill to absolute position

For `a`, `A`, `h`, and `H`, a number after the format character indicates how long the string is. For example, `A25` means a 25-character space-padded string. For other format characters, a following number means how many of that type appear consecutively in a string. Use `*` to take the rest of the available data.

You can convert between data types with `unpack( )`. This example fills the array `\$ascii` with the ASCII values of each character in `\$s`:

```\$s = 'platypus';
\$ascii = unpack('c*',\$s);
print_r(\$ascii);
Array
(
[1] => 112
[2] => 108
[3] => 97
[4] => 116
[5] => 121
[6] => 112
[7] => 117
[8] => 115
)```

Documentation on `pack( )` at http://www.php.net/pack and `unpack( )` at http://www.php.net/unpack .