1.14.1 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.
1.14.2 Solution
$packed = pack('S4',1974,106,28225,32725);
$nums = unpack('S4',$packed);
1.14.3 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
)
Format character
|
Data type
|
|---|---|
a
|
NUL-padded string
|
A
|
Space-padded string
|
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
)