Start · Sprachen · PHP · Referenz · pack

pack

Funktion

Packt Daten anhand eines Format-Strings in eine binäre Zeichenkette (Byte-String).

seit PHP 4.0.0 Kategorie: misc

Signatur

pack(string $format, mixed ...$values): string

Beschreibung

pack() wandelt PHP-Variablen gemäß einem Format-String in eine binäre Darstellung um. Die Funktion ist das Gegenstück zu unpack() und wird überall dort benötigt, wo binäre Protokolle (z. B. Netzwerk-Pakete, Datei-Header, BMP-Bilder, ZIP-Strukturen) erzeugt oder Daten für C-Libraries vorbereitet werden müssen.

Der Format-String besteht aus einem oder mehreren Zeichen, die jeweils einen Datentyp beschreiben, gefolgt von einer optionalen Wiederholungsanzahl (z. B. N3 für drei unsigned long-Werte in Big-Endian). Die gängigsten Format-Codes sind: a/A (Zeichenkette, NUL-/Space-aufgefüllt), c/C (signed/unsigned char), s/S (signed/unsigned short, 16 Bit), l/L (signed/unsigned long, 32 Bit), q/Q (signed/unsigned long long, 64 Bit), n/N (unsigned short/long in Network-Byte-Order), v/V (unsigned short/long in Little-Endian), f/d (float/double in der Maschinen-Darstellung), x (NUL-Byte einfügen), X (eine Position zurück), @ (absoluter Position).

Die Funktion ist besonders nützlich beim Erstellen eigener binärer Datei-Formate oder beim Kommunizieren mit externen Systemen über Sockets, bei denen exakte Byte-Anordnungen erforderlich sind. In Kombination mit fwrite() lassen sich kompakte Binär-Dateien schreiben, die wesentlich kleiner als Text-Äquivalente sind.

Ein häufiger Fallstrick ist die Byte-Reihenfolge (Endianness): Plattformabhängige Codes (s, l, q, f, d) richten sich nach dem Host-System. Für portable Protokolle sollte man stets plattformunabhängige Codes (n, N, v, V, J, P) verwenden.

Parameter

Name Typ Default Beschreibung
$format Pflicht string Format-String, der die Typen und Reihenfolge der zu packenden Werte beschreibt. Jedes Zeichen steht für einen Datentyp (z. B. N = unsigned long Big-Endian), optional gefolgt von einer Ganzzahl als Wiederholungszähler oder * für alle restlichen Argumente.
$values mixed Beliebig viele Werte, die entsprechend dem Format-String in die Binär-Zeichenkette gepackt werden. Anzahl und Typen müssen zum Format-String passen.

Rückgabewert

Typ
string|false
Beschreibung
Gibt die erzeugte binäre Zeichenkette zurück. Liefert false, wenn der Format-String ungültig ist oder die Anzahl der übergebenen Werte nicht zum Format passt (seit PHP 8.0 wird bei Typfehlern stattdessen ein ValueError geworfen).

Beispiele

Einfaches Packen von Integer-Werten (Big-Endian / Network-Byte-Order)

<?php
// Zwei 32-Bit-Ganzzahlen (unsigned) in Network-Byte-Order packen
$binary = pack('NN', 0xDEADBEEF, 42);

// Rohbytes als Hex ausgeben
echo bin2hex($binary); // deadbeef0000002a

// Wieder entpacken zur Verifikation
$data = unpack('N1first/N1second', $binary);
print_r($data);
// Array ( [first] => 3735928559 [second] => 42 )
deadbeef0000002a Array ( [first] => 3735928559 [second] => 42 )

Einen minimalen BMP-Datei-Header erzeugen

<?php
// Einfaches 1x1-Pixel BMP-Bild (schwarz) in eine Datei schreiben
// BMP-Header: Signatur, Dateigröße, reserviert, Pixel-Offset
$width  = 1;
$height = 1;
$pixelDataSize = 4; // 1 Pixel, 32-Bit
$headerSize    = 54;
$fileSize      = $headerSize + $pixelDataSize;

// BITMAPFILEHEADER (14 Bytes)
$fileHeader = pack('a2Vx4V', 'BM', $fileSize, $headerSize);

// BITMAPINFOHEADER (40 Bytes)
$infoHeader = pack(
    'VVVvvVVVVVV',
    40,        // Größe des Info-Headers
    $width,    // Bildbreite
    $height,   // Bildhöhe
    1,         // Ebenen
    32,        // Bits pro Pixel
    0,         // Kompression (keine)
    $pixelDataSize,
    2835, 2835, // Pixel pro Meter (72 dpi)
    0, 0
);

// Pixeldaten: 1 Pixel schwarz (BGRA)
$pixelData = pack('V', 0x000000FF);

$bmp = $fileHeader . $infoHeader . $pixelData;
file_put_contents('/tmp/test.bmp', $bmp);
echo 'BMP geschrieben, Größe: ' . strlen($bmp) . ' Bytes';
BMP geschrieben, Größe: 58 Bytes

String und gemischte Typen packen

<?php
// Einen 8-Byte-Bezeichner (null-terminiert), gefolgt von einer
// 16-Bit-Version (LE) und einem 64-Bit-Timestamp (BE) erzeugen
$label     = 'MYAPP';
$version   = 3;
$timestamp = time();

$packet = pack('a8vJ', $label, $version, $timestamp);

echo 'Paketlänge: ' . strlen($packet) . ' Bytes' . PHP_EOL; // 18 Bytes
echo 'Hex: ' . bin2hex($packet) . PHP_EOL;

// Zurücklesen
$parsed = unpack('a8label/vversion/Jtimestamp', $packet);
echo 'Label: '   . rtrim($parsed['label'], "\0") . PHP_EOL;
echo 'Version: ' . $parsed['version'] . PHP_EOL;
echo 'Zeit: '    . date('Y-m-d', $parsed['timestamp']) . PHP_EOL;
Paketlänge: 18 Bytes Hex: 4d59415050000000030000000067... Label: MYAPP Version: 3 Zeit: 2025-01-01

// Wichtig · Fallstricke

Byte-Reihenfolge: Die Codes s, S, l, L, q, Q, i, I, f und d sind plattformabhängig. Für portable Binärformate immer n/N (Big-Endian) oder v/V (Little-Endian) bzw. J/P (64-Bit, ab PHP 5.6.3) verwenden.

Zeichenketten (a vs. A): a füllt mit NUL-Bytes auf, A mit Leerzeichen. Beim Lesen mit unpack() entfernt A nachfolgende Leerzeichen, a nicht — auf diesen Unterschied achten, wenn NUL-Bytes im String relevant sind.

PHP 7.2+: pack() löst bei falscher Anzahl von Werten eine E_WARNING aus. Ab PHP 8.0 wird bei ungültigem Format-Code ein ValueError geworfen statt false zurückzugeben.

Sicherheit: Da pack() beliebige Bytes erzeugt, dürfen die erzeugten Daten niemals ungeprüft in SQL-Abfragen oder HTML-Ausgaben einfließen. Immer geeignete Escape-Funktionen (addslashes(), htmlspecialchars()) oder Prepared Statements verwenden.