Unpack: примеры (PHP)

Функция unpack в PHP: полный обзор с практическими примерами
Раздел: Преобразование типов/форматов
unpack(string format, string string [, int offset]): array|false

Функция unpack() в PHP выполняет распаковку бинарных данных из строки в массив согласно заданному формату. Она является обратной функцией для pack() и часто используется при обработке файловых форматов, сетевых протоколов или данных из системных вызовов.

Аргументы функции

Функция имеет два обязательных и один необязательный аргумент:

  • format (string) - Строка формата, определяющая структуру данных. Состоит из кодов форматов и опциональных модификаторов.
  • string (string) - Обрабатываемая бинарная строка.
  • offset (int) - Необязательное смещение в байтах для начала распаковки. Добавлен в PHP 7.1.
Коды форматов

Основные коды: a (строка с NUL-дополнением), A (строка с пробельным дополнением), h (шестнадцатеричная строка, младший полубайт первый), H (шестнадцатеричная строка, старший полубайт первый), c (знаковый char), C (беззнаковый char), s (знаковый short, порядок байт зависит от модификатора), S (беззнаковый short), n (беззнаковый short, big endian), v (беззнаковый short, little endian), i (знаковый integer), I (беззнаковый integer), l (знаковый long), L (беззнаковый long), N (беззнаковый long, big endian), V (беззнаковый long, little endian), q (знаковый long long), Q (беззнаковый long long), J (беззнаковый long long, big endian), P (беззнаковый long long, little endian), f (float), d (double), x (пропуск байта), X (возврат на байт), Z (строка с NUL-дополнением, удаление завершающих NULL).

Базовые примеры

Распаковка беззнаковых short в little-endian порядке:

$result = unpack('vshort', hex2bin('0100'));
print_r($result);
Array
(
    [short] => 1
)

Распаковка строки с фиксированной длиной:

$result = unpack('a5str', 'hello\0\0');
print_r($result);
Array
(
    [str] => hello
)

Использование смещения:

$result = unpack('vshort', hex2bin('00000100'), 2);
print_r($result);
Array
(
    [short] => 1
)
Альтернативы в PHP

pack() - Обратная функция для упаковки данных в бинарную строку. Используется совместно с unpack.

sscanf() - Парсит строку согласно формату, но предназначена для текстовых данных, а не бинарных.

bin2hex() и hex2bin() - Преобразуют бинарные данные в шестнадцатеричное представление и обратно. Полезны для отладки.

ord() - Возвращает ASCII-код первого символа строки. Подходит для получения значений отдельных байтов.

Альтернативы в других языках

Unpack в Python

Модуль struct предоставляет функции pack и unpack:

import struct
result = struct.unpack('
(1,)

Unpack в Javascript

Используются объекты DataView или TypedArray:

let buffer = new Uint8Array([1, 0]).buffer;
let view = new DataView(buffer);
let result = view.getUint16(0, true);
console.log(result);
1

Unpack в MySQL

Функция UNHEX() преобразует шестнадцатеричную строку в бинарные данные, но не выполняет распаковку структур.

Типичные ошибки

Несоответствие длины строки формату вызывает предупреждение и возвращает false:

$result = unpack('v', 'a');
var_dump($result);
Warning: unpack(): Argument #2 ($string) is too short
bool(false)

Использование неверного кода формата:

$result = unpack('z', 'ab');
var_dump($result);
Warning: unpack(): Invalid format type z
bool(false)

Игнорирование возвращаемых ключей при повторяющихся кодах:

$result = unpack('v2', hex2bin('01000200'));
print_r($result);
Array
(
    [1] => 1
    [2] => 2
)
Изменения в PHP

В PHP 7.1 добавлен необязательный параметр offset.

В PHP 7.2 добавлены коды формата q, Q, J и P для 64-битных целых чисел.

В PHP 8.0 изменено поведение при ошибках: некоторые предупреждения преобразованы в исключения TypeError и ValueError.

Расширенные примеры

Распаковка заголовка PNG-файла (первые 8 байт):

Пример php
$pngHeader = "\x89PNG\r\n\x1a\n";
$result = unpack('a8signature', $pngHeader);
print_r($result);
Array
(
    [signature] => �PNG


)

Обработка IPv4-адреса:

Пример php
$ip = inet_pton('192.168.1.1');
$result = unpack('C4octets', $ip);
print_r($result);
Array
(
    [octets1] => 192
    [octets2] => 168
    [octets3] => 1
    [octets4] => 1
)

Распаковка данных с именами ключей:

Пример php
$data = hex2bin('01000200');
$result = unpack('vfirst/vsecond', $data);
print_r($result);
Array
(
    [first] => 1
    [second] => 2
)

Использование модификатора * для оставшихся данных:

Пример php
$data = hex2bin('010002000300');
$result = unpack('vfirst/v*rest', $data);
print_r($result);
Array
(
    [first] => 1
    [rest1] => 2
    [rest2] => 3
)

Работа с числами с плавающей точкой:

Пример php
$float = pack('f', 3.14);
$result = unpack('fval', $float);
print_r($result);
Array
(
    [val] => 3.1400001049042
)

PHP unpack function comments

En
Unpack Unpack data from binary string