web-dev-qa-db-fra.com

Comment lire un seul fichier dans une archive Zip

J'ai besoin de lire le contenu d'un seul fichier, "test.txt", à l'intérieur d'un fichier Zip. L'ensemble du fichier Zip est un très gros fichier (2 Go) et contient beaucoup de fichiers (10 000 000), et en tant que tel, l'extraction de l'ensemble n'est pas une solution viable pour moi. Comment lire un seul fichier?

35
e-info128

Essayez d'utiliser le Zip:// wrapper :

$handle = fopen('Zip://test.Zip#test.txt', 'r'); 
$result = '';
while (!feof($handle)) {
  $result .= fread($handle, 8192);
}
fclose($handle);
echo $result;

Vous pouvez utiliser file_get_contents aussi:

$result = file_get_contents('Zip://test.Zip#test.txt'); 
echo $result;
54
Rocket Hazmat

Veuillez noter que la solution @ Rocket-Hazmat fopen peut provoquer une boucle infinie si un fichier Zip est protégé par un mot de passe, car fopen échouera et feof sera toujours vrai si un erreur se produit.

Vous pouvez le changer en

$handle = fopen('Zip://file.Zip#file.txt', 'r');
$result = '';
if ($handle) {
    while (!feof($handle)) {
        $result .= fread($handle, 8192);
    }
    fclose($handle);
}
echo $result;

Cela résout le problème de boucle infinie, mais si votre fichier Zip est protégé par un mot de passe, vous pouvez voir quelque chose comme

Avertissement: file_get_contents (Zip: //file.Zip#file.txt): échec d'ouverture du flux: échec de l'opération

Il y a cependant une solution

Depuis PHP 7.2 le support des archives cryptées a été ajouté.

Vous pouvez donc le faire de cette façon pour les deux file_get_contents et fopen

$options = [
    'Zip' => [
        'password' => '1234'
    ]
];

$context = stream_context_create($options);
echo file_get_contents('Zip://file.Zip#file.txt', false, $context);

Une meilleure solution cependant pour vérifier si un fichier existe ou non avant de le lire sans se soucier des archives cryptées utilise ZipArchive

$Zip = new ZipArchive;
if ($Zip->open('file.Zip') !== TRUE) {
    exit('failed');
}
if ($Zip->locateName('file.txt') !== false) {
    echo 'File exists';
} else {
    echo 'File does not exist';
}

Cela fonctionnera (pas besoin de connaître le mot de passe)

Remarque: pour localiser un dossier à l'aide de la méthode locateName, vous devez le passer comme folder/ avec une barre oblique à la fin.

0
Rain