W3docs

unpack()

Aprende la función unpack() de PHP: firma, códigos de formato, orden de bytes y ejemplos prácticos con pack().

Las cadenas PHP son en realidad secuencias de bytes sin procesar, lo que las convierte en un contenedor natural para datos binarios: cabeceras de imágenes, paquetes de red, formatos de archivo y tramas de protocolo. La función unpack() lee ese flujo de bytes sin procesar y lo convierte en valores PHP ordinarios (enteros, flotantes, cadenas) con los que puedes trabajar. Este artículo cubre la firma de la función, sus códigos de formato, el orden de bytes, los errores más comunes y cómo se complementa con pack().

Sintaxis

unpack(string $format, string $data, int $offset = 0): array|false
ParámetroDescripción
$formatUna cadena de formato que describe cómo interpretar los bytes (los códigos se listan a continuación).
$dataLa cadena binaria de la que se leerá.
$offsetPosición en bytes desde la que empezar a leer (añadido en PHP 7.1). El valor por defecto es 0.

Devuelve un array asociativo con los valores desempaquetados, o false en caso de error. unpack() es la función inversa de pack(): el diseño que escribes con pack() lo recuperas con los mismos códigos de formato.

Primer ejemplo

La cadena de formato es una secuencia de uno o más códigos. Cada código es una sola letra para un tipo de dato, un contador de repetición opcional y un nombre opcional.

php— editable, runs on the server

Aquí "C*" significa "leer cada byte restante como un entero sin signo de 8 bits". El contador de repetición * consume todos los bytes disponibles. Cuando no se proporciona un nombre, unpack() numera los resultados empezando por 1 (no 0):

Array
(
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
)

Códigos de formato

Cada código corresponde a un número fijo de bytes. Los más comunes son:

CódigoTipoTamaño
C / cChar sin signo / con signo1 byte
nShort sin signo, big-endian2 bytes
vShort sin signo, little-endian2 bytes
S / sShort sin signo / con signo, orden de bytes de la máquina2 bytes
NLong sin signo, big-endian4 bytes
VLong sin signo, little-endian4 bytes
L / lLong sin signo / con signo, orden de bytes de la máquina4 bytes
f / dFloat / double, orden de la máquina4 / 8 bytes
a / ACadena (rellena con NUL / con espacios)según se especifique
H / hCadena hexadecimal, nibble alto / bajo primeropor nibble

Un número después de un código lo repite (C4 lee cuatro chars); un * lee todos los bytes restantes.

Nombrar los campos

Los formatos binarios reales están compuestos de campos mixtos, por lo que generalmente se le da un nombre a cada uno y se separan los códigos con /:

php— editable, runs on the server

"C2chars/Sint/Nlong" lee los dos primeros bytes como chars1/chars2, los dos siguientes como un short int en orden de máquina, y los últimos cuatro como un long long big-endian:

Array
(
    [chars1] => 1
    [chars2] => 2
    [int] => 1027
    [long] => 84281096
)

Cuando un código tiene un contador de repetición y un nombre, unpack() añade un índice al nombre (chars1, chars2, …) para que los valores no colisionen.

El orden de bytes importa

Los mismos cuatro bytes representan números diferentes según el orden de bytes. N/n son big-endian (orden de red); V/v son little-endian (nativo en x86); S/L siguen la máquina anfitriona y por tanto no son portables. Para datos que cruzan máquinas — un formato de archivo o un protocolo de red — elige siempre un código con endianness explícito para que el resultado sea el mismo en todas partes.

<?php
$bytes = "\x01\x00\x00\x00";
print_r(unpack("Vlittle", $bytes)); // little-endian: 1
print_r(unpack("Nbig", $bytes));    // big-endian: 16777216
?>
Array
(
    [little] => 1
)
Array
(
    [big] => 16777216
)

Ida y vuelta con pack()

Dado que unpack() es el reflejo de pack(), puedes serializar valores en un blob binario compacto y recuperarlos directamente con el mismo formato:

<?php
$packed = pack("nN", 1027, 84281096); // build the bytes
$result = unpack("nshort/Nlong", $packed);
print_r($result);
?>
Array
(
    [short] => 1027
    [long] => 84281096
)

Errores comunes

  • Las claves empiezan en 1. Los resultados sin nombre se indexan desde 1, lo que sorprende al iterar. Nombra tus campos o recuerda el desplazamiento.
  • Los nombres con contadores de repetición reciben un sufijo de índice (byte1, byte2), por lo que unpack("C4byte", ...) produce byte1byte4, no un solo byte.
  • Los códigos de orden de máquina (S, L, s, l) no son portables. Usa n/N o v/V para cualquier dato almacenado o transmitido.
  • false si hay muy pocos datos. Si el formato requiere más bytes de los que contiene $data, unpack() devuelve false y emite una advertencia — comprueba el valor de retorno antes de usarlo.

Conclusión

La función unpack() convierte bytes sin procesar en valores PHP usando códigos de formato compactos, y es la mitad lectora del par pack(). Domina los códigos de endianness y la sintaxis de nomenclatura de campos, y podrás analizar prácticamente cualquier cabecera de archivo binario o trama de red. Para convertir datos binarios en una cadena hexadecimal legible, consulta bin2hex().

Práctica

Práctica
¿Qué hace la función 'unpack' de PHP?
¿Qué hace la función 'unpack' de PHP?
Was this page helpful?