Start · Sprachen · PHP · Referenz · stream_copy_to_stream

stream_copy_to_stream

Funktion

Kopiert Daten von einem Stream in einen anderen, wahlweise mit Längen- und Offset-Begrenzung.

seit PHP 5.0.0 Kategorie: io

Signatur

stream_copy_to_stream(resource $from, resource $to, int $length = -1, int $offset = 0): int|false

Beschreibung

stream_copy_to_stream() liest Daten aus dem Stream $from und schreibt sie direkt in den Stream $to. Die Funktion arbeitet intern gepuffert und ist daher deutlich effizienter als ein manuelles Lesen und Schreiben in einer Schleife – insbesondere bei großen Dateien oder Netzwerk-Streams, da kein vollständiger Puffer im Arbeitsspeicher aufgebaut werden muss.

Mit dem Parameter $length lässt sich die maximale Anzahl zu kopierender Bytes begrenzen. Wird -1 übergeben (Standardwert), werden alle verfügbaren Daten bis zum Ende des Quell-Streams kopiert. Der Parameter $offset ermöglicht es, den Lesevorgang an einer bestimmten Byte-Position im Quell-Stream zu beginnen.

Typische Einsatzszenarien sind das Kopieren von Dateien über Stream-Wrapper (fopen()), das Weiterleiten von HTTP-Antworten, das Befüllen von temporären Streams (php://temp, php://memory) oder das Zusammenführen mehrerer Streams in einen Ausgabe-Stream.

Beide Streams müssen vor dem Aufruf geöffnet und gültig sein. Der Quell-Stream sollte lesbar, der Ziel-Stream schreibbar sein, andernfalls gibt die Funktion false zurück.

Parameter

Name Typ Default Beschreibung
$from Pflicht resource Der Quell-Stream, aus dem die Daten gelesen werden. Muss eine gültige, lesbare Stream-Ressource sein.
$to Pflicht resource Der Ziel-Stream, in den die Daten geschrieben werden. Muss eine gültige, schreibbare Stream-Ressource sein.
$length int -1 Maximale Anzahl zu kopierender Bytes. Bei -1 (Standard) werden alle verfügbaren Daten bis zum Ende des Quell-Streams kopiert.
$offset int 0 Byte-Position im Quell-Stream, ab der der Kopiervorgang beginnt. Standard ist 0 (Anfang des Streams). Beachte: Nicht alle Stream-Typen unterstützen Seeks, daher kann ein Offset bei manchen Streams nicht funktionieren.

Rückgabewert

Typ
int|false
Beschreibung
Gibt die Anzahl der tatsächlich kopierten Bytes als int zurück. Im Fehlerfall (z. B. ungültige Stream-Ressourcen, fehlende Berechtigungen) wird false zurückgegeben.

Beispiele

Datei effizient in eine andere kopieren

<?php
$source = fopen('/var/data/original.csv', 'rb');
$destination = fopen('/var/data/kopie.csv', 'wb');

if ($source === false || $destination === false) {
    die('Fehler beim Öffnen der Streams.');
}

$bytesCopied = stream_copy_to_stream($source, $destination);

fclose($source);
fclose($destination);

echo "Kopiert: {$bytesCopied} Bytes";
Kopiert: 204800 Bytes

Nur einen Teilbereich eines Streams kopieren (Offset und Länge)

<?php
// Quell-Stream mit Beispielinhalt erstellen
$source = fopen('php://memory', 'r+b');
fwrite($source, 'AAAA__NUTZDATEN__ZZZZ');
rewind($source);

// Nur die mittleren Bytes kopieren (ab Byte 6, max. 9 Bytes)
$destination = fopen('php://memory', 'w+b');
$bytesCopied = stream_copy_to_stream($source, $destination, 9, 6);

rewind($destination);
$result = stream_get_contents($destination);

fclose($source);
fclose($destination);

echo "Kopiert: {$bytesCopied} Bytes\n";
echo "Inhalt: {$result}";
Kopiert: 9 Bytes Inhalt: NUTZDATEN

HTTP-Response-Body direkt in eine Datei streamen

<?php
// Kontext für HTTP-Stream
$context = stream_context_create([
    'http' => [
        'method' => 'GET',
        'header' => 'Accept: application/octet-stream',
    ]
]);

$remote = fopen('https://example.com/largefile.bin', 'rb', false, $context);
$local  = fopen('/tmp/largefile.bin', 'wb');

if ($remote && $local) {
    $total = stream_copy_to_stream($remote, $local);
    echo "Download abgeschlossen: {$total} Bytes gespeichert.";
}

fclose($remote);
fclose($local);
Download abgeschlossen: 1048576 Bytes gespeichert.

// Wichtig · Fallstricke

Offset-Unterstützung: Nicht alle Stream-Typen sind seekbar (z. B. Netzwerk-Sockets, php://stdin). Bei einem $offset > 0 versucht die Funktion intern einen Seek; schlägt dieser fehl, beginnt sie dennoch am aktuellen Stream-Zeiger. Das Verhalten kann daher je nach Stream-Typ abweichen.

Speichereffizienz: Im Gegensatz zu file_get_contents() + file_put_contents() hält stream_copy_to_stream() nicht den gesamten Inhalt im Arbeitsspeicher, was es zur bevorzugten Methode für große Datenmengen macht.

Rückgabewert prüfen: Da die Funktion bei einem Fehler false zurückgibt und 0 ein gültiger Rückgabewert (leerer Stream) ist, sollte ein strikter Vergleich (=== false) zur Fehlerprüfung verwendet werden.