W3docs

unpack()

Scopri la funzione PHP unpack(): panoramica, codici di formato, endianness, insidie comuni ed esempi pratici di utilizzo.

Le stringhe PHP sono fondamentalmente sequenze di byte grezzi, il che le rende un contenitore naturale per dati binari — intestazioni di immagini, pacchetti di rete, formati di file e frame di protocollo. La funzione unpack() legge quel flusso di byte grezzi e lo converte in valori PHP ordinari (interi, float, stringhe) con cui puoi lavorare. Questo articolo tratta la firma della funzione, i suoi codici di formato, l'endianness, le insidie più comuni e come si abbina a pack().

Sintassi

unpack(string $format, string $data, int $offset = 0): array|false
ParametroDescrizione
$formatUna stringa di formato che descrive come interpretare i byte (i codici sono elencati di seguito).
$dataLa stringa binaria da leggere.
$offsetPosizione in byte da cui iniziare la lettura (aggiunto in PHP 7.1). Il valore predefinito è 0.

Restituisce un array associativo dei valori decompressi, oppure false in caso di errore. unpack() è l'inverso di pack(): qualsiasi layout scritto con pack() può essere riletto con gli stessi codici di formato.

Primo esempio

La stringa di formato è una sequenza di uno o più codici. Ogni codice è una singola lettera per un tipo di dato, un conteggio di ripetizioni opzionale e un nome opzionale.

php— editable, runs on the server

Qui "C*" significa "leggi ogni byte rimanente come un intero senza segno a 8 bit". Il conteggio di ripetizioni * consuma tutti i byte disponibili. Quando non si fornisce un nome, unpack() numera i risultati a partire da 1 (non da 0):

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

Codici di formato

Ogni codice corrisponde a un numero fisso di byte. I più comuni:

CodiceTipoDimensione
C / cChar senza segno / con segno1 byte
nShort senza segno, big-endian2 byte
vShort senza segno, little-endian2 byte
S / sShort senza segno / con segno, ordine byte della macchina2 byte
NLong senza segno, big-endian4 byte
VLong senza segno, little-endian4 byte
L / lLong senza segno / con segno, ordine byte della macchina4 byte
f / dFloat / double, ordine della macchina4 / 8 byte
a / AString (NUL-padded / space-padded)come specificato
H / hStringa esadecimale, nibble alto / basso per primoper nibble

Un numero dopo un codice lo ripete (C4 legge quattro char); un * legge tutti i byte rimanenti.

Assegnare nomi ai campi

I formati binari reali sono composti da campi misti, quindi di solito si assegna un nome a ciascuno e si separano i codici con /:

php— editable, runs on the server

"C2chars/Sint/Nlong" legge i primi due byte come chars1/chars2, i successivi due come uno short int nell'ordine della macchina, e gli ultimi quattro come un long big-endian long:

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

Quando un codice ha un conteggio di ripetizioni e un nome, unpack() aggiunge un indice al nome (chars1, chars2, …) in modo che i valori non collidano.

L'endianness è importante

Gli stessi quattro byte significano numeri diversi a seconda dell'ordine dei byte. N/n sono big-endian (ordine di rete); V/v sono little-endian (nativo x86); S/L seguono la macchina host e quindi non sono portabili. Per dati che transitano tra macchine diverse — un formato di file o un protocollo di rete — scegli sempre un codice con endianness esplicita in modo che il risultato sia lo stesso ovunque.

<?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-trip con pack()

Poiché unpack() è l'immagine speculare di pack(), puoi serializzare valori in un blob binario compatto e rileggerli direttamente con il formato corrispondente:

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

Insidie comuni

  • Le chiavi partono da 1. I risultati senza nome sono indicizzati a partire da 1, il che può creare confusione nei cicli. Assegna nomi ai campi o ricorda l'offset.
  • I nomi con conteggio di ripetizioni ottengono un suffisso indice (byte1, byte2), quindi unpack("C4byte", ...) restituisce byte1byte4, non un unico byte.
  • I codici nell'ordine della macchina (S, L, s, l) non sono portabili. Usa n/N o v/V per qualsiasi dato memorizzato o trasmesso.
  • false con dati insufficienti. Se il formato richiede più byte di quanti ne contenga $data, unpack() restituisce false ed emette un avviso — controlla il valore restituito prima di usarlo.

Conclusione

La funzione unpack() converte byte grezzi in valori PHP usando codici di formato compatti, ed è la metà di lettura della coppia pack(). Padroneggia i codici di endianness e la sintassi di denominazione dei campi e potrai analizzare praticamente qualsiasi intestazione di file binario o frame di rete. Per convertire dati binari in una stringa esadecimale leggibile, vedi bin2hex().

Pratica

Pratica
Cosa fa la funzione PHP 'unpack'?
Cosa fa la funzione PHP 'unpack'?
Was this page helpful?