Manipuler une chaîne de 30 millions de caractères
Je suis le téléchargement d'un fichier CSV à partir d'un autre serveur comme un flux de données à partir d'un fournisseur.
J'utilise curl pour obtenir le contenu du fichier et de l'enregistrer dans une variable appelée $contents
.
Je peux accéder à la partie, mais j'ai essayé d'exploser par \r
et \n
pour obtenir un tableau de lignes, mais il échoue avec un "out of memory' erreur.
Je echo strlen($contents)
et c'est environ 30,5 millions de caractères.
J'ai besoin de manipuler les valeurs et les insérer dans une base de données. Que dois-je faire pour éviter l'allocation de la mémoire des erreurs?
source d'informationauteur JD Isaacks | 2009-08-27
Vous devez vous connecter pour publier un commentaire.
PHP est l'étouffement parce qu'il est à cours de mémoire. Au lieu d'avoir curl remplir une variable PHP avec le contenu du fichier, utilisez la
option pour enregistrer le fichier sur le disque au lieu.
Puis, une fois le fichier enregistré, au lieu d'utiliser le
file
oufile_get_contents
fonctions (qui serait de charger tout le fichier en mémoire, tuant PHP), l'utilisationfopen
et fgets pour lire le fichier ligne par ligne.Comme d'autres réponses a dit :
CURLOPT_FILE
Mais, vous ne pouvez vraiment créer un fichier ; vous pourriez vouloir travailler avec les données dans la mémoire... l'Utiliser dès qu'il "arrive".
Une solution possible pourrait être definind vous propre gestionnaire de flux, et d'utiliser celui-ci, au lieu d'un fichier réel, avec
CURLOPT_FILE
Tout d'abord, voir :
stream_wrapper_register
Les streamWrapper classe
Et maintenant, passons à un exemple.
Tout d'abord, nous allons créer notre gestionnaire de flux de classe :
Ce que je fais, c'est :
stream_write
Ensuite, nous avons enregistrer ce gestionnaire de flux, pour être utilisé avec le pseudo-protocole "test" :
Et, maintenant, nous faisons de notre demande curl, comme nous le feriez lors de la rédaction d'un "vrai" fichier, comme d'autres réponses proposées :
Remarque nous ne travaillons pas avec un vrai fichier, mais avec notre pseudo-protocole.
De cette façon, chaque fois qu'un bloc de données arrive,
MyStream::stream_write
méthode sera appelée, et sera en mesure de travailler sur une petite quantité de données (quand je l'ai testé, j'ai toujours eu de 8192 octets, quelle que soit la valeur que j'ai utilisé pourCURLOPT_BUFFERSIZE
)Quelques remarques :
Encore, j'espère que cette aide 😉
Amusez-vous !
Darren Cuire commentaire de Pascal MARTIN réponse est vraiment intéressant. Moderne, PHP+Curl versions, la
CURLOPT_WRITEFUNCTION
option peut être définie de sorte CURL appelle une fonction de rappel pour chaque reçu "morceau" de données. Plus précisément, le "callable" sera reçu à deux paramètres, le premier avec l'invocation curl objet, et la seconde avec le segment de données. La fonction doit retournerstrlen($data)
pour curl continuer à envoyer plus de données.Callables peut être des méthodes en PHP. À l'aide de tout cela, j'ai développé une solution que je trouve plus lisible que la précédente (bien que Pascal Martin réponse est vraiment super, les choses ont changé depuis). J'ai utilisé les attributs de la simplicité, mais je suis sûr que les lecteurs pourraient s'adapter et d'améliorer le code. Vous pouvez même annuler la demande CURL, quand un certain nombre de lignes (ou d'octets) ont été atteints. J'espère que cela serait utile pour les autres.
Vous pourriez envisager de les sauver dans un fichier temporaire, puis le lire ligne par ligne à l'aide de
fgets
oufgetcsv
.De cette façon, vous évitez les initiales grand tableau que vous obtenez à partir d'exploser telle une chaîne de grande taille.