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
)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 7.1 добавлен необязательный параметр offset.
В PHP 7.2 добавлены коды формата q, Q, J и P для 64-битных целых чисел.
В PHP 8.0 изменено поведение при ошибках: некоторые предупреждения преобразованы в исключения TypeError и ValueError.
Распаковка заголовка PNG-файла (первые 8 байт):
$pngHeader = "\x89PNG\r\n\x1a\n";
$result = unpack('a8signature', $pngHeader);
print_r($result);Array
(
[signature] => �PNG
)Обработка IPv4-адреса:
$ip = inet_pton('192.168.1.1');
$result = unpack('C4octets', $ip);
print_r($result);Array
(
[octets1] => 192
[octets2] => 168
[octets3] => 1
[octets4] => 1
)Распаковка данных с именами ключей:
$data = hex2bin('01000200');
$result = unpack('vfirst/vsecond', $data);
print_r($result);Array
(
[first] => 1
[second] => 2
)Использование модификатора * для оставшихся данных:
$data = hex2bin('010002000300');
$result = unpack('vfirst/v*rest', $data);
print_r($result);Array
(
[first] => 1
[rest1] => 2
[rest2] => 3
)Работа с числами с плавающей точкой:
$float = pack('f', 3.14);
$result = unpack('fval', $float);
print_r($result);Array
(
[val] => 3.1400001049042
)