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?
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;
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 commefolder/
avec une barre oblique à la fin.