In PHP lautet der allgemeine Prozess wie folgt:
$zip = zip_open("example.zip");
if (is_resource($zip)) {
while ($entry = zip_read($zip)) {
echo "Name: " . zip_entry_name($entry) . "\n";
if (zip_entry_open($zip, $entry, "r")) {
$contents = zip_entry_read($entry, 1024);
echo "Content: " . $contents . "\n";
zip_entry_close($entry);
}
}
zip_close($zip);
}
Der obige Code ist eine typische Verwendung durch die offizielle PHP -Dokumentation. Es funktioniert in vielen Szenarien gut, aber solange es etwas komplizierter ist oder der Inhalt liest eine bestimmte Größe, entsteht das Problem.
Der Inhalt kann nicht gelesen werden : ZIP_ENTRY_READ () gibt eine leere Zeichenfolge zurück.
Einige Dateien werden auf halbem Weg durch das Lesen unterbrochen : Es können nur teilweise Inhalte gelesen werden.
Melden Sie einen Fehler oder festgefahren : Einige komprimierte Pakete führen dazu, dass die PHP -Ausführung festhält.
Die Lektüre ist verwirrend : Der Inhalt mehrerer Einträge wird zusammen verschachtelt.
Diese Probleme haben eines gemeinsam: Probleme verschwinden normalerweise, solange Sie zu anderen Bibliotheken wie Ziparchive wechseln. Dies zeigt, dass das Problem wahrscheinlich nicht in der ZIP -Datei selbst, sondern in dem Verwendungs- oder Implementierungsmechanismus der zip_* -Funktion liegt.
ZIP_READ () ist im Wesentlichen ein Iterator, der den Lesezeiger des Reißverschlusses jedes Mal, wenn er aufgerufen wird, intern beibehält. Wenn Sie während des Lesevorgangs den nächsten Zip_Read () anrufen (zum Beispiel, bevor Sie einen Eintrag gelesen haben), wird der Lesestatus des vorherigen Eintrags zerstört.
ZIP_ENTRY_READ () garantiert nicht, dass alle Daten gleichzeitig gelesen werden, insbesondere wenn Sie in einer festen Länge (z. B. 1024) übergeben, müssen Sie durchlaufen, um zu lesen, bis die leere Zeichenfolge zurückgegeben wird, andernfalls geht der Inhalt verloren gehen.
Dies ist auch der Kern dieses Artikels: ZIP_ENTRY_READ () hängt im Wesentlichen von dem derzeit von ZIP_READ () verwalteten Eintragsstatus ab. Wenn Sie beim Aufrufen von zip_entry_read () (auch in einem anderen logischen Zweig) Zip_read () erneut aufrufen, wird das frühere Verhalten unterbrochen.
Geben Sie nicht den nächsten ZIP_READ () ein, wenn der aktuelle Eintragsinhalt nicht gelesen wurde. Andernfalls wird der Lesezeiger im Voraus verschoben, was zu verlorenen oder falschen Inhalten führt.
while ($entry = zip_read($zip)) {
zip_entry_open($zip, $entry, "r");
$content = "";
while ($data = zip_entry_read($entry, 1024)) {
$content .= $data;
}
echo $content;
zip_entry_close($entry);
}
Einige Zip-Dateien können durch nicht standardmäßige Tools komprimiert werden und können unregelmäßige Strukturen enthalten. Es wird empfohlen, die Ziparchive -Klasse zu verwenden, um mit der IsReadable () -Methode zusammenzuarbeiten, um die Integrität zuerst zu überprüfen.
$zip = new ZipArchive();
if ($zip->open('example.zip') === TRUE) {
// Überprüfungslogik
$zip->close();
}
Obwohl Funktionen wie ZIP_OPEN () präzise und einfach zu bedienen sind, wurden sie frühzeitig als experimentell (oder sogar nicht empfohlen) markiert, während die Ziparchive -Klasse leistungsfähiger und stabiler ist und mit komplexen ZIP -Dateien besser fertig werden kann.
$zip = new ZipArchive();
if ($zip->open('example.zip') === TRUE) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$entryName = $zip->getNameIndex($i);
echo "File: " . $entryName . "\n";
$stream = $zip->getStream($entryName);
if ($stream) {
while (!feof($stream)) {
echo fread($stream, 1024);
}
fclose($stream);
}
}
$zip->close();
}
Diese Methode ist nicht nur effizienter, sondern hat auch nicht das Problem von zip_entry_read () les unterbrochen und eignet sich besser für die Verwendung in Produktionsumgebungen.
Der Grund, warum zip_read () und zip_entry_read () häufig auftreten, wenn sie gemeinsam verwendet werden, ist, dass sie eine starke Abhängigkeit vom internen Zeigerzustand haben. Sobald Sie in der Verarbeitungsreihenfolge nicht vorsichtig sind und Rhythmus lesen, sind Sie anfällig für logische Störungen. Es wird empfohlen, dass Projekte mit hohen Stabilitätsanforderungen für ZIP -Operationen Priorität für die Verwendung von Ziparchive anstelle dieser Reihe von zugrunde liegenden Funktionen erhalten sollten.
Wenn Sie die Function -Familie in ZIP_* verwenden müssen, stellen Sie immer sicher, dass die Leserreihenfolge streng ist, lesen Sie den Inhalt jedes Eintrags intakt und vermeiden Sie es, die nächste Leserunde einzugeben, ohne den Eintrag zu schließen.
Referenzdokument: https://www.php.net/manual/zh/ref.zip.php