W3docs

unpack()

Découvrez la fonction PHP unpack() : fonctionnement, codes de format, boutisme et exemples pratiques pour lire des données binaires.

Les chaînes PHP ne sont en réalité que des séquences d'octets bruts, ce qui en fait un conteneur naturel pour les données binaires — en-têtes d'images, paquets réseau, formats de fichiers et trames de protocoles. La fonction unpack() lit ce flux d'octets bruts et le transforme en valeurs PHP ordinaires (entiers, flottants, chaînes) avec lesquelles vous pouvez travailler. Cet article couvre la signature de la fonction, ses codes de format, le boutisme, les pièges courants et la façon dont elle s'utilise avec pack().

Syntaxe

unpack(string $format, string $data, int $offset = 0): array|false
ParamètreDescription
$formatUne chaîne de format décrivant comment interpréter les octets (les codes sont listés ci-dessous).
$dataLa chaîne binaire à lire.
$offsetPosition en octets à partir de laquelle commencer la lecture (ajouté en PHP 7.1). Par défaut 0.

La fonction retourne un tableau associatif des valeurs décompressées, ou false en cas d'échec. unpack() est l'inverse de pack() : quelle que soit la disposition écrite avec pack(), vous la relisez avec les mêmes codes de format.

Premier exemple

La chaîne de format est une séquence d'un ou plusieurs codes. Chaque code est une seule lettre pour un type de données, un nombre de répétitions optionnel et un nom optionnel.

php— editable, runs on the server

Ici "C*" signifie « lire chaque octet restant comme un entier non signé de 8 bits ». Le compteur de répétition * consomme tous les octets disponibles. Lorsque vous ne fournissez pas de nom, unpack() numérote les résultats en commençant à 1 (et non 0) :

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

Codes de format

Chaque code correspond à un nombre fixe d'octets. Les plus courants :

CodeTypeTaille
C / cChar non signé / signé1 octet
nShort non signé, big-endian2 octets
vShort non signé, little-endian2 octets
S / sShort non signé / signé, ordre machine2 octets
NLong non signé, big-endian4 octets
VLong non signé, little-endian4 octets
L / lLong non signé / signé, ordre machine4 octets
f / dFloat / double, ordre machine4 / 8 octets
a / AChaîne (complétée par NUL / espaces)selon spécification
H / hChaîne hexadécimale, demi-octet de poids fort / faible en premierpar demi-octet

Un nombre après un code le répète (C4 lit quatre chars) ; un * lit tous les octets restants.

Nommer les champs

Les formats binaires réels sont composés de champs mixtes, il est donc courant de donner un nom à chacun et de séparer les codes par / :

php— editable, runs on the server

"C2chars/Sint/Nlong" lit les deux premiers octets en tant que chars1/chars2, les deux suivants en tant que short int dans l'ordre machine, et les quatre derniers en tant que long long big-endian :

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

Lorsqu'un code possède un compteur de répétition et un nom, unpack() ajoute un index au nom (chars1, chars2, …) pour éviter les collisions.

Le boutisme est important

Les mêmes quatre octets représentent des nombres différents selon l'ordre des octets. N/n sont big-endian (ordre réseau) ; V/v sont little-endian (natif x86) ; S/L suivent la machine hôte et ne sont donc pas portables. Pour des données échangées entre machines — un format de fichier ou un protocole réseau — choisissez toujours un code à boutisme explicite afin que le résultat soit identique partout.

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

Aller-retour avec pack()

Puisque unpack() est le miroir de pack(), vous pouvez sérialiser des valeurs dans un blob binaire compact et les relire directement avec le format correspondant :

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

Pièges courants

  • Les clés commencent à 1. Les résultats sans nom sont indexés à partir de 1, ce qui peut surprendre lors d'une boucle. Nommez vos champs ou pensez à cet décalage.
  • Les noms avec compteur de répétition reçoivent un suffixe d'index (byte1, byte2), donc unpack("C4byte", ...) produit byte1byte4, pas un seul byte.
  • Les codes d'ordre machine (S, L, s, l) ne sont pas portables. Utilisez n/N ou v/V pour tout ce qui est stocké ou transmis.
  • false si les données sont insuffisantes. Si le format exige plus d'octets que $data n'en contient, unpack() retourne false et émet un avertissement — vérifiez la valeur de retour avant de l'utiliser.

Conclusion

La fonction unpack() transforme des octets bruts en valeurs PHP à l'aide de codes de format compacts, et constitue la moitié lecture de la paire pack(). Maîtrisez les codes de boutisme et la syntaxe de nommage des champs, et vous pourrez analyser pratiquement n'importe quel en-tête de fichier binaire ou trame réseau. Pour convertir des données binaires en chaîne hexadécimale lisible, consultez bin2hex().

Pratique

Pratique
Que fait la fonction PHP 'unpack' ?
Que fait la fonction PHP 'unpack' ?
Was this page helpful?