W3docs

pack()

En este artículo nos centramos en la función pack() de PHP: qué hace, cómo funciona y ejemplos de su uso.

Este artículo cubre la función pack() de PHP: qué hace, el mini-lenguaje de cadenas de formato que utiliza, cómo el orden de bytes (endianness) afecta al resultado, y ejemplos prácticos que puedes ejecutar, incluido el viaje de vuelta con unpack().

Qué hace pack()

pack() toma valores PHP ordinarios (enteros, flotantes, cadenas) y los dispone byte a byte en una única cadena binaria — una cadena cuyos caracteres son bytes en crudo en lugar de texto legible.

pack(string $format, mixed ...$values): string
  • $format — una cadena de formato compacta que describe, en orden, cómo debe codificarse cada valor (su tipo, tamaño y orden de bytes).
  • ...$values — uno o más valores a codificar, emparejados de izquierda a derecha con los códigos de formato.

El valor de retorno es una cadena binaria. Como esos bytes normalmente no son imprimibles, los ejemplos a continuación pasan el resultado por bin2hex() para que puedas ver exactamente qué bytes se produjeron (dos dígitos hexadecimales = un byte).

¿Cuándo lo usarías?

Se recurre a pack() siempre que PHP tenga que hablar un formato definido en bytes en crudo en lugar de texto:

  • Protocolos binarios — construcción de paquetes de red donde una cabecera es "una longitud de 2 bytes seguida de un id de 4 bytes."
  • Formatos de archivo binarios — escritura de trozos PNG, cabeceras WAV o cualquier diseño con campos de ancho fijo.
  • Auxiliares de hashing/crypto — convertir un resumen hexadecimal en su forma de bytes en crudo para pasarlo a hash_hmac() u openssl_*.
  • Comunicación con sistemas C/embebidos que esperan campos de tamaño fijo y endianness fijo.

Para almacenamiento PHP-a-PHP sencillo, serialize() o json_encode() son más amigables; pack() brilla cuando el diseño de bytes en sí importa.

Un primer ejemplo

php— editable, runs on the server

123 en hexadecimal es 0x7b. El código de formato N significa "long sin signo (4 bytes), orden de bytes de red," por lo que el valor se rellena hasta cuatro bytes y se escribe con el byte más significativo primero: 00 00 00 7b.

Leyendo la cadena de formato

Una cadena de formato es una secuencia de códigos de formato, cada uno seguido opcionalmente de un contador de repetición:

N    one unsigned long
N4   four unsigned longs in a row
N*   as many unsigned longs as there are remaining values
A10  a 10-character space-padded string

Puedes concatenar códigos para describir un registro completo. Los valores que pasas deben alinearse con los códigos en orden:

<?php
// A 2-byte short (1) followed by a 4-byte long (16909060)
$header = pack('nN', 1, 16909060);

echo bin2hex($header); // 000101020304
?>

Aquí n produce 00 01 (el short 1) y N produce 01 02 03 04 (el long 16909060, que es 0x01020304). Los bytes aparecen exactamente en el orden en que se escribieron los códigos.

Orden de bytes (endianness)

El mismo número puede almacenarse con sus bytes en dos órdenes opuestos, y pack() te proporciona un código para cada uno:

  • Big-endian (también conocido como orden de bytes de red) almacena primero el byte más significativo — códigos n (short) y N (long).
  • Little-endian almacena primero el byte menos significativo — códigos v (short) y V (long).
<?php
echo bin2hex(pack('N', 1)), "\n"; // 00000001  (big-endian)
echo bin2hex(pack('V', 1)), "\n"; // 01000000  (little-endian)
?>

Esto importa porque el receptor debe usar la misma convención para leer los datos de vuelta. Los protocolos de red estandarizan en big-endian (N/n); muchos formatos de archivo (y volcados de memoria x86) usan little-endian (V/v). En caso de duda, elige N/n para intercambio — eso es lo que garantiza el "orden de bytes de red."

Códigos de formato más comunes

Una selección de los códigos más utilizados (consulta el manual de PHP para la lista completa):

CódigoSignificado
aCadena rellena con NUL
ACadena rellena con espacios
c / CChar con / sin signo (1 byte)
s / SShort con / sin signo, orden de bytes nativo (2 bytes)
n / NShort / long sin signo, big-endian
v / VShort / long sin signo, little-endian
f / dFloat / double, formato de la máquina
H / hCadena hexadecimal, nibble alto / bajo primero

Los códigos de cadena usan el contador de repetición como ancho de campo, no como contador de valores:

<?php
echo pack('A6', 'PHP'), "|"; // PHP   |  (padded to 6 chars with spaces)
?>

Viaje de ida y vuelta: pack() y luego unpack()

pack() escribe bytes; unpack() los lee de vuelta en valores PHP. Para recuperar los datos originales debes describir el mismo diseño, y unpack() necesita adicionalmente un nombre para cada campo:

<?php
// Encode two fields
$binary = pack('Nn', 65536, 7);

// Decode using the same layout, naming each field
$values = unpack('Nfirst/nsecond', $binary);

echo $values['first'], ' ', $values['second']; // 65536 7
?>

La barra diagonal (/) separa los campos con nombre en el formato de unpack(). Si los diseños de ambos lados no coinciden, obtendrás basura — la codificación y la decodificación están estrechamente acopladas.

Errores comunes

  • Los códigos y los valores deben alinearse. Pasar menos valores que códigos genera una advertencia y devuelve false; los valores extra se ignoran en silencio (a menos que hayas usado *).
  • El desbordamiento de enteros se trunca, no se marca. pack('C', 300) conserva solo el byte bajo (300 & 0xFF = 44) en lugar de generar un error — valida los rangos tú mismo.
  • Los códigos nativos (s, S, i, l, flotantes) no son portables. Su tamaño y orden de bytes dependen de la plataforma. Para datos que cruzan máquinas, prefiere los códigos explícitos de big/little-endian.
  • El resultado es una cadena binaria. No la imprimas con echo en una página HTML ni la compares como texto; inspecciónala con bin2hex() o escríbela en un archivo/flujo binario.

Para la operación inversa, continúa con el capítulo de unpack(). Para ver los bytes en crudo en tus propios experimentos, el auxiliar bin2hex() utilizado a lo largo de esta página es invaluable.

Conclusión

pack() convierte valores PHP en una cadena binaria controlada con precisión, con un mini-lenguaje de formato compacto para el tipo de campo, el tamaño y el orden de bytes. Úsalo siempre que debas producir bytes que otro sistema lea en sus propios términos — protocolos binarios, formatos de archivo o rutinas de criptografía — y combínalo con unpack() para leer los datos de vuelta.

Práctica

Práctica
¿Qué hace la función pack() en PHP?
¿Qué hace la función pack() en PHP?
Was this page helpful?