Lecture de très gros fichiers en PHP
fopen
échoue quand j'essaie de lire dans un fichier de taille très modérée dans PHP
. {[3] } le fait étouffer, bien que les fichiers plus petits autour de 100k
soient très bien. j'ai lu qu'il est parfois nécessaire de recompiler PHP
avec le drapeau -D_FILE_OFFSET_BITS=64
afin de lire des fichiers sur 20 concerts ou quelque chose de ridicule, mais ne devrais-je pas avoir aucun problème avec un fichier 6 meg? Finalement, nous aurons envie de lire dans des fichiers qui sont autour de 100 megs, et ce serait bien de pouvoir les ouvrir et ensuite les lire ligne par ligne avec fgets comme je suis capable de le faire avec des fichiers plus petits.
Quelles sont vos astuces/solutions pour lire et faire des opérations sur des fichiers très volumineux dans PHP
?
Update: voici un exemple d'un simple codeblock qui échoue sur mon fichier 6 meg-PHP ne semble pas lancer d'erreur, il renvoie simplement false. Peut-être que je fais quelque chose d'extrêmement stupide?
$rawfile = "mediumfile.csv";
if($file = fopen($rawfile, "r")){
fclose($file);
} else {
echo "fail!";
}
Une autre mise à jour: merci à tous pour votre aide, il s'est avéré être quelque chose d'incroyablement stupide - un problème d'autorisations. Mon petit fichier inexplicablement eu des autorisations de lecture lorsque le fichier plus grand n'a pas. Doh!
8 réponses
Êtes-vous sûr que c'est fopen
qui échoue et pas le paramètre de délai d'expiration de votre script? La valeur par défaut est généralement d'environ 30 secondes, et si votre fichier prend plus de temps à lire, il peut être déclenché.
Une autre chose à considérer peut être la limite de mémoire sur votre script-la lecture du fichier dans un tableau peut trébucher sur cela, alors vérifiez votre journal des erreurs pour les avertissements de mémoire.
Si aucun des éléments ci-dessus ne pose de problème, vous pourriez envisager d'utiliser fgets
pour lisez le fichier ligne par ligne, en le traitant au fur et à mesure.
$handle = fopen("/tmp/uploadfile.txt", "r") or die("Couldn't get handle");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
// Process buffer here..
}
fclose($handle);
}
Modifier
PHP ne semble pas lancer d'erreur, il renvoie simplement false.
Le chemin d'accès à $rawfile
est-il correct par rapport à l'endroit où le script s'exécute? Essayez peut-être de définir un chemin absolu ici pour le nom de fichier.
A fait 2 tests avec un fichier 1.3 GB et un fichier 9.5 GB.
1.3 GO
À l'Aide de fopen()
Ce processus a utilisé 15555 ms pour ses calculs.
Il a passé 169 ms dans les appels système.
À l'Aide de file()
Ce processus a utilisé 6983 ms pour ses calculs.
Il a passé 4469 ms dans les appels système.
9.5 GO
À l'Aide de fopen()
Ce processus a utilisé 113559 ms pour ses calculs.
Il a dépensé 2532 ms dans les appels système.
À l'Aide de file()
Ce processus a utilisé 8221 ms pour ses calculs.
Il a passé 7998 ms dans les appels système.
Semble file()
est plus rapide.
J'ai utilisé fopen pour ouvrir des fichiers vidéo pour le streaming, en utilisant un script php comme serveur de streaming vidéo, et je n'ai eu aucun problème avec des fichiers de plus de 50/60 MB.
Eh bien, vous pouvez essayer d'utiliser la fonction readfile si vous voulez juste sortir le fichier.
Si ce n'est pas le cas, peut - être vous devriez penser à la conception de l'application, pourquoi voulez-vous ouvrir de tels fichiers volumineux sur les requêtes web?
Si le problème est causé par l'atteinte de la limite de mémoire, vous pouvez essayer de lui donner une valeur plus élevée (cela peut fonctionner ou non en fonction de la configuration de php).
Cela définit la limite de mémoire à 12 Mo
ini\_set("memory_limit","12M");
Pour moi, fopen()
a été très lente avec des fichiers de plus de 1 mo, file()
est beaucoup plus rapide.
Juste essayer de lire les lignes 100 à la fois et de créer des insertions par lots, fopen()
prend 37 secondes vs file()
prend 4 secondes. Doit être cette étape string->array
intégrée dans file()
J'essaierais toutes les options de gestion de fichiers pour voir ce qui fonctionnera le mieux dans votre application.
Vous ne savez pas si vous avez résolu le problème. J'essayais aussi de traiter un gros fichier tout en rencontrant un site web qui, je pense, pourrait être la réponse.
En utilisant la commande yield.