Position actuelle: Accueil> Derniers articles> Pourquoi zip_read () et zip_entry_read () ont-ils toujours des problèmes lorsqu'ils sont utilisés ensemble? Partagez le problème de l'enquête

Pourquoi zip_read () et zip_entry_read () ont-ils toujours des problèmes lorsqu'ils sont utilisés ensemble? Partagez le problème de l'enquête

M66 2025-06-28

1. Les utilisations de base de zip_read () et zip_entry_read ()

En PHP, le processus général est le suivant:

 $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);
}

Le code ci-dessus est une utilisation typique donnée par la documentation officielle PHP. Il fonctionne bien dans de nombreux scénarios, mais tant qu'il est un peu plus compliqué, ou que le contenu lit dépasse une certaine taille, le problème se pose.


2. Questions fréquemment posées

  1. Le contenu ne peut pas être lu : zip_entry_read () renvoie une chaîne vide.

  2. Certains fichiers sont interrompus à mi-chemin par la lecture : seul le contenu partiel peut être lu.

  3. Signaler une erreur ou coincée : certains packages compressés entraîneront la collaboration de l'exécution de PHP.

  4. L'ordre de lecture est déroutant : le contenu d'une entrée multiple est entrelacé ensemble.

Ces problèmes ont une chose en commun: les problèmes disparaissent généralement tant que vous passez à d'autres bibliothèques, comme Ziparchive. Cela montre que le problème n'est probablement pas dans le fichier ZIP lui-même, mais dans le mécanisme d'utilisation ou de mise en œuvre de la fonction ZIP_ * .


3. Analyse de la cause profonde du problème

1. Zip_read () est avec état

zip_read () est essentiellement un itérateur qui maintient en interne le pointeur de lecture du zip à chaque fois qu'il est appelé. Si vous appelez le prochain zip_read () pendant le processus de lecture (par exemple, avant d'avoir fini de lire une entrée), l'état de lecture de l'entrée précédente sera détruit.

2. Zip_entry_read () est un flux unique en lecture

zip_entry_read () ne garantit pas que toutes les données seront lues en même temps, surtout lorsque vous passez une longueur fixe (telle que 1024), vous devez passer à travers pour lire jusqu'à ce que la chaîne vide soit retournée, sinon le contenu sera perdu.

3. Zip_entry_read () et zip_read () interfèrent les uns avec les autres

C'est également le cœur de cet article: zip_entry_read () dépend essentiellement de l'état d'entrée actuellement maintenu par zip_read () . Si vous appelez à nouveau zip_read () lorsque vous appelez zip_entry_read () (même dans une autre branche logique), l'ancien comportement sera interrompu.


4. Enquêter sur les idées et les suggestions

? Idée 1: assurez-vous que zip_entry_read () est lu complètement avant d'appeler zip_read ()

Ne saisissez pas le prochain zip_read () lorsque le contenu de l'entrée actuel n'a pas été lu, sinon le pointeur de lecture sera déplacé à l'avance, entraînant un contenu perdu ou incorrect.

 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);
}

? Idée 2: Vérifiez si le zip est endommagé ou a des codes spéciaux

Certains fichiers zip peuvent être compressés par des outils non standard et peuvent contenir des structures irrégulières. Il est recommandé d'utiliser la classe Ziparchive pour coopérer avec la méthode Isreadable () pour vérifier d'abord l'intégrité.

 $zip = new ZipArchive();
if ($zip->open('example.zip') === TRUE) {
    // Logique de vérification
    $zip->close();
}

? Idée 3: Envisagez d'utiliser Ziparchive au lieu des fonctions de la série Zip_ *

Bien que des fonctions telles que zip_open () soient concises et faciles à utiliser, elles ont été marquées comme expérimentales (ou même pas recommandées) dès le début, tandis que la classe ziparchive est plus puissante et stable, et peut mieux faire face à des fichiers zip complexes.


5. Un autre exemple: implémentation ziparchive

 $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();
}

Cette méthode est non seulement plus efficace, mais n'a pas non plus le problème de l'interruption de lecture zip_entry_read () , et est plus adapté à une utilisation dans les environnements de production.


6. Conclusion

La raison pour laquelle zip_read () et zip_entry_read () se produisent fréquemment lorsqu'ils sont utilisés ensemble est qu'ils ont une forte dépendance à l'état du pointeur interne. Une fois que vous ne faites pas attention à l'ordre de traitement et au rythme de lecture, vous êtes sujet aux troubles logiques. Il est recommandé que les projets avec des exigences de stabilité élevées pour les opérations ZIP soient prioritaires à l'utilisation de Ziparchive au lieu de cet ensemble de fonctions sous-jacentes.

Si vous devez utiliser la famille de fonctions zip_ * , assurez-vous toujours que l'ordre de lecture est rigoureux, lisez le contenu de chaque entrée intacte et évitez d'entrer dans la prochaine série de lecture sans fermer l'entrée.

Document de référence: https://www.php.net/manual/zh/ref.zip.php