W3docs

unpack()

Neste artigo, exploramos a função PHP unpack(), seu funcionamento e exemplos práticos de uso com dados binários.

Strings PHP são, na verdade, sequências de bytes brutos, o que as torna um contêiner natural para dados binários — cabeçalhos de imagem, pacotes de rede, formatos de arquivo e quadros de protocolo. A função unpack() lê esse fluxo de bytes brutos e o transforma em valores PHP comuns (inteiros, floats, strings) com os quais você pode trabalhar. Este artigo cobre a assinatura da função, seus códigos de formato, endianness, armadilhas comuns e como ela se combina com pack().

Sintaxe

unpack(string $format, string $data, int $offset = 0): array|false
ParâmetroDescrição
$formatUma string de formato descrevendo como interpretar os bytes (os códigos estão listados abaixo).
$dataA string binária a ser lida.
$offsetPosição em bytes a partir da qual começar a leitura (adicionado no PHP 7.1). O padrão é 0.

Retorna um array associativo com os valores desempacotados, ou false em caso de falha. unpack() é o inverso de pack(): qualquer layout que você escrever com pack() pode ser lido de volta com os mesmos códigos de formato.

Um primeiro exemplo

A string de formato é uma sequência de um ou mais códigos. Cada código é uma única letra para um tipo de dado, uma contagem de repetição opcional e um nome opcional.

php— editable, runs on the server

Aqui "C*" significa "ler cada byte restante como um inteiro de 8 bits sem sinal". A contagem de repetição * consome todos os bytes disponíveis. Quando você não fornece um nome, unpack() numera os resultados começando em 1 (não 0):

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

Códigos de formato

Cada código corresponde a um número fixo de bytes. Os mais comuns:

CódigoTipoTamanho
C / cChar sem sinal / com sinal1 byte
nShort sem sinal, big-endian2 bytes
vShort sem sinal, little-endian2 bytes
S / sShort sem sinal / com sinal, ordem de bytes da máquina2 bytes
NLong sem sinal, big-endian4 bytes
VLong sem sinal, little-endian4 bytes
L / lLong sem sinal / com sinal, ordem de bytes da máquina4 bytes
f / dFloat / double, ordem da máquina4 / 8 bytes
a / AString (preenchida com NUL / espaço)conforme especificado
H / hString hexadecimal, nibble alto / baixo primeiropor nibble

Um número após um código o repete (C4 lê quatro chars); um * lê todos os bytes restantes.

Nomeando os campos

Formatos binários reais são compostos de campos mistos, então geralmente você dá a cada um um nome e separa os códigos com /:

php— editable, runs on the server

"C2chars/Sint/Nlong" lê os dois primeiros bytes como chars1/chars2, os próximos dois como um short int na ordem da máquina, e os últimos quatro como um long long big-endian:

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

Quando um código tem uma contagem de repetição e um nome, unpack() acrescenta um índice ao nome (chars1, chars2, …) para que os valores não colidam.

Endianness importa

Os mesmos quatro bytes significam números diferentes dependendo da ordem dos bytes. N/n são big-endian (ordem de rede); V/v são little-endian (nativo do x86); S/L seguem a máquina host e, portanto, não são portáveis. Para dados que cruzam máquinas — um formato de arquivo ou um protocolo de rede — sempre escolha um código com endianness explícito para que o resultado seja o mesmo em qualquer lugar.

<?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
)

Round-tripping com pack()

Como unpack() é o espelho de pack(), você pode serializar valores em um blob binário compacto e lê-los de volta com o formato correspondente:

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

Armadilhas comuns

  • As chaves começam em 1. Resultados sem nome são indexados a partir de 1, o que confunde ao fazer loops. Nomeie seus campos ou lembre-se do offset.
  • Nomes com contagens de repetição recebem um sufixo de índice (byte1, byte2), então unpack("C4byte", ...) retorna byte1byte4, não um único byte.
  • Códigos de ordem da máquina (S, L, s, l) não são portáveis. Use n/N ou v/V para qualquer coisa armazenada ou transmitida.
  • false quando há poucos dados. Se o formato exige mais bytes do que $data contém, unpack() retorna false e emite um aviso — verifique o valor de retorno antes de usá-lo.

Conclusão

A função unpack() transforma bytes brutos em valores PHP usando códigos de formato compactos, e é a metade de leitura do par pack(). Domine os códigos de endianness e a sintaxe de nomenclatura de campos e você poderá analisar praticamente qualquer cabeçalho de arquivo binário ou quadro de rede. Para converter dados binários em uma string hexadecimal legível, consulte bin2hex().

Prática

Prática
O que a função PHP 'unpack' faz?
O que a função PHP 'unpack' faz?
Was this page helpful?