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!

22
demandé sur Alive to Die 2008-10-02 17:11:45

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.

40
répondu ConroyP 2008-10-02 13:29:17

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.

7
répondu Al-Punk 2018-09-21 00:11:17

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.

1
répondu Enrico Murru 2008-10-02 13:21:46

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?

0
répondu Fionn 2008-10-02 13:16:57

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");
0
répondu Juan Pablo Califano 2015-10-13 06:45:12

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.

0
répondu RightClick 2018-05-11 05:30:25

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.

Https://www.sitepoint.com/performant-reading-big-files-php/

0
répondu Dean Chiu 2018-08-03 15:40:02
-1
répondu Ólafur Waage 2008-10-02 13:28:44