unpack()
Erfahren Sie mehr über die PHP-Funktion unpack(): Syntax, Formatcodes, Byte-Reihenfolge und Praxisbeispiele.
PHP-Strings sind im Grunde Folgen roher Bytes, was sie zu einem natürlichen Behälter für Binärdaten macht — Bild-Header, Netzwerkpakete, Dateiformate und Protokollrahmen. Die Funktion unpack() liest diesen rohen Byte-Strom und wandelt ihn in gewöhnliche PHP-Werte (Ganzzahlen, Fließkommazahlen, Strings) um, mit denen Sie arbeiten können. Dieser Artikel behandelt die Signatur der Funktion, ihre Formatcodes, die Byte-Reihenfolge, häufige Fallstricke und die Verwendung zusammen mit pack().
Syntax
unpack(string $format, string $data, int $offset = 0): array|false| Parameter | Beschreibung |
|---|---|
$format | Ein Formatstring, der beschreibt, wie die Bytes interpretiert werden sollen (Codes sind unten aufgeführt). |
$data | Der binäre String, aus dem gelesen wird. |
$offset | Byteposition, ab der gelesen werden soll (ab PHP 7.1 hinzugefügt). Standardmäßig 0. |
Die Funktion gibt ein assoziatives Array der entpackten Werte zurück oder false bei einem Fehler. unpack() ist die Umkehrfunktion von pack(): Welches Layout Sie mit pack() schreiben, lesen Sie mit denselben Formatcodes zurück.
Ein erstes Beispiel
Der Formatstring besteht aus einer oder mehreren Codes. Jeder Code besteht aus einem einzelnen Buchstaben für einen Datentyp, einer optionalen Wiederholungsanzahl und einem optionalen Namen.
Hier bedeutet "C*" „lies jeden verbleibenden Byte als vorzeichenloses 8-Bit-Integer". Der Wiederholungszähler * verarbeitet alle verfügbaren Bytes. Wenn Sie keinen Namen angeben, nummeriert unpack() die Ergebnisse ab 1 (nicht 0):
Array
(
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
)Formatcodes
Jeder Code entspricht einer festen Anzahl von Bytes. Die häufigsten:
| Code | Typ | Größe |
|---|---|---|
C / c | Vorzeichenloser / vorzeichenbehafteter Char | 1 Byte |
n | Vorzeichenloser Short, Big-Endian | 2 Bytes |
v | Vorzeichenloser Short, Little-Endian | 2 Bytes |
S / s | Vorzeichenloser / vorzeichenbehafteter Short, Maschinenreihenfolge | 2 Bytes |
N | Vorzeichenloser Long, Big-Endian | 4 Bytes |
V | Vorzeichenloser Long, Little-Endian | 4 Bytes |
L / l | Vorzeichenloser / vorzeichenbehafteter Long, Maschinenreihenfolge | 4 Bytes |
f / d | Float / Double, Maschinenreihenfolge | 4 / 8 Bytes |
a / A | String (NUL-aufgefüllt / Leerzeichen-aufgefüllt) | wie angegeben |
H / h | Hex-String, High / Low Nibble zuerst | pro Nibble |
Eine Zahl nach einem Code wiederholt ihn (C4 liest vier Chars); ein * liest alle verbleibenden Bytes.
Felder benennen
Echte Binärformate bestehen aus gemischten Feldern, daher gibt man jedem einen Namen und trennt die Codes mit /:
"C2chars/Sint/Nlong" liest die ersten beiden Bytes als chars1/chars2, die nächsten zwei als maschinengeordneten Short int und die letzten vier als Big-Endian-Long long:
Array
(
[chars1] => 1
[chars2] => 2
[int] => 1027
[long] => 84281096
)Wenn ein Code eine Wiederholungsanzahl und einen Namen hat, hängt unpack() einen Index an den Namen an (chars1, chars2, …), damit die Werte sich nicht überschneiden.
Byte-Reihenfolge ist wichtig
Dieselben vier Bytes bedeuten unterschiedliche Zahlen, je nach Byte-Reihenfolge. N/n sind Big-Endian (Netzwerkreihenfolge); V/v sind Little-Endian (x86-nativ); S/L folgen der Host-Maschine und sind daher nicht portierbar. Für Daten, die zwischen Maschinen ausgetauscht werden — ein Dateiformat oder ein Netzwerkprotokoll — wählen Sie immer einen expliziten Endian-Code, damit das Ergebnis überall gleich ist.
<?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
)Hin- und Rückumwandlung mit pack()
Da unpack() das Spiegelbild von pack() ist, können Sie Werte in einen kompakten Binär-Blob serialisieren und sie mit dem passenden Format direkt zurücklesen:
<?php
$packed = pack("nN", 1027, 84281096); // build the bytes
$result = unpack("nshort/Nlong", $packed);
print_r($result);
?>Array
(
[short] => 1027
[long] => 84281096
)Häufige Fallstricke
- Schlüssel beginnen bei 1. Unbenannte Ergebnisse sind 1-indiziert, was beim Durchlaufen zu Verwirrung führt. Benennen Sie Ihre Felder oder denken Sie an den Offset.
- Namen mit Wiederholungsanzahl erhalten ein Indexsuffix (
byte1,byte2), sodassunpack("C4byte", ...)byte1…byte4liefert, nicht ein einzelnesbyte. - Maschinengeordnete Codes (
S,L,s,l) sind nicht portierbar. Verwenden Sien/Noderv/Vfür alles, was gespeichert oder übertragen wird. falsebei zu wenig Daten. Wenn das Format mehr Bytes verlangt, als$dataenthält, gibtunpack()falsezurück und gibt eine Warnung aus — überprüfen Sie den Rückgabewert, bevor Sie ihn verwenden.
Fazit
Die Funktion unpack() wandelt rohe Bytes mit kompakten Formatcodes in PHP-Werte um und ist die lesende Hälfte des pack()-Paares. Beherrschen Sie die Endian-Codes und die Feldbenennungssyntax, und Sie können nahezu jeden Binärdatei-Header oder Netzwerkrahmen parsen. Um Binärdaten stattdessen in einen lesbaren Hex-String umzuwandeln, siehe bin2hex().