Lire gros fichier >3GB

[Résolu/Fermé]
Signaler
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
-
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
-
Bonjour,

Je voudrais lire un très gros fichier texte de plusieurs Go. Le problème est que le compilateur PHP de mon hébergeur est un 32 bits et donc la taille maximale du integer est inférieure à la taille de mon fichier en bytes.

J'utilise la fonction fseek pour me déplacer dans le fichier. Et j'ai essayé de contourner le problème de différente façons (récursivité, boucle) mais rien n'y fait... quand le curseur est arrivé à une position égale à la taille max du int dans le fichier, il ne peut pas avancer plus loin.

Mon code qui ne fonctionne pas :

function fseek_bigfile($file,$pos,$first=0){

  if($first) fseek($fp,0,SEEK_SET);

  $pos=floatval($pos);

  if($pos<=PHP_INT_MAX){

   fseek($file,intval($pos),SEEK_CUR);

  }else{

   while($pos>PHP_INT_MAX){
    fseek($file,PHP_INT_MAX,SEEK_CUR);
    $pos-=floatval(PHP_INT_MAX);
    echo " ".$pos;
   }

   fseek($file,intval($pos),SEEK_CUR);
  }
 }


Si vous avez une solution, merci de me répondre! ^^

si il y en a pas, je pense que je serai contraint de scinder mon fichier en plusieurs petits fichiers

Merci pour vos remarques!!

Qui ne tente rien n'a rien

8 réponses

Messages postés
14821
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 septembre 2021
300
Si ton hébergeur ne peut pas faire plus de 2Go, tu devra découper ton fichier, il n'y a pas de méthode pour contourner une restriction système (à ma connaissance).
1
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 42674 internautes nous ont dit merci ce mois-ci

Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
190
Bonjour,

Je peux mettre des fichiers de taille que je veux, c'est pas ça le problème. Actuellement je travaille qu'en local. L'inconvénient c'est qu'il n'y a pas possibilité de déplacer le curseur plus loin que 2 milliards et quelque dans mon fichier pour cause que ça dépasse la taille du int.

L'idéal ce serait de trouver en php une fonction équivalente à celle que j'utilise fseek(file, float start, float whence) mais qui prend des float en paramètre.

La solution de la boucle pour les gros fichiers je l'avait pioché sur le site de PHP (http://php.net/manual/fr/function.fseek.php#112647) mais visiblement ça n'a pas l'air de fonctionner chez moi...


1
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 42674 internautes nous ont dit merci ce mois-ci

Messages postés
14821
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 septembre 2021
300
Tu as un message d'erreur ?
As-tu essayer de faire un print des valeurs des variables ?
Je n'ai jamais eu à faire à ce genre de cas, et je n'ai pas de fichiers de plus de 2Go sur mon serveur (et l'upload d'un seul serait un peu long).
Messages postés
14821
Date d'inscription
vendredi 14 mars 2003
Statut
Modérateur
Dernière intervention
18 septembre 2021
300
Bonsoir,

Pourquoi as-tu besoin d'un aussi gros fichier ?
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
190
Bonsoir,

Pour stocker des décimales (10 Go).

Je voudrais juste l'exploiter en lecture de A à Z.
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
190
Bonsoir,

oui je fais des print. j'ai vu qu'il y a un echo dans le bout de code que j'ai posté d'ailleurs. Et ce que j'ai pu voir par l'affichage c'est que fseek() me renvoie false lorsque je veut bouger mon curseur de plus de 2 147 483 647 (PHP_INT_MAX) caractères depuis le début du fichier.

admettons que je sois à 1 milliard de caractères depuis le début début de mon fichier fseek($file,1 000 000 000,SEEK_SET);

et si je me déplace ensuite de 1 500 000 000 caractères par rapport à ma position actuelle fseek($file,1 500 000 000,SEEK_CUR); la fonction me renverra false.

J'avais pu constater qu'il revenait en fait automatiquement au début du fichier. Si je reviens à mon exemple, je serai finalement positionné à (2 500 000 000-2 147 483 647) caractères au lieu d'idéalement à 2 500 000 000 caractères depuis le début du fichier.

du coup je pense que je vais travailler avec plusieurs fichiers de plus petite taille même si ça va pas me faciliter la tâche dans le développement.

sinon voilà pour quel genre de site je travaille avec des fichiers de cette taille : http://www.piproject.org/decimals/

mais j'avais pas ce problème là auparavant quand je l'ai fait vu que je m'étais limité à 1 milliard^^

merci

Qui ne tente rien n'a rien
Messages postés
4761
Date d'inscription
dimanche 12 juin 2011
Statut
Contributeur
Dernière intervention
23 octobre 2020
1 277
'lut, il me vient une idée assez louche mais qui pourrait marcher, et qui ne marcherais que chez un hébergeur permettant d'utiliser la fonction
shell_exec
et tournant sous Linux ou OSX...
Tu pourrais utiliser la commande
dd
pour sortir les octets demandés du fichier voulu, avec comme options
if=fichier_decimales iflag=skip_bytes skip=<decalage en octets> bs=<octets a lire>
.
shell_exec
te renverrais les données voulues sous forme de string, sans problème de taille de fichier si ton environnement le permet (à savoir, que dd utilise les fonctions Unix définies lors du Large File Summit, permettant l'accès aux fichiers de + de 4Go sur des systèmes 32bit).
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
190
excellente idée toute de même je trouve
faut que je teste ça...
en tout cas merci de m'avoir fait approcher de la fonction shell_exec que je ne connaissais pas dans php. normalement mon hébergeur c'est un Linux si ils m'ont pas menti après faut que je vois si mon hébergeur autorise l'exécution de scripts shell aussi
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
190
visiblement l'hébergeur accepte la commande dd sans problème sur un fichier stocké. ça va me permettre de me remettre un peu au shell tout ça... Je te remercie beaucoup! Il faut uploader la bête de 10Go maintenant^^
Messages postés
216
Date d'inscription
lundi 2 décembre 2013
Statut
Membre
Dernière intervention
10 octobre 2016
21
Le code suivant permet de travailler ligne à ligne et permet de ce fait la gestion de très gros fichiers ...
Après j'ai jamais eu à l'utiliser avec des fichiers vraiment très très gros, comme dans ton cas, mais je ne pense pas que ce soit un soucis, surtout en local ou tu n'es pas limité sur le temps d'exécution de ton script.

<?php
$fichier = fopen('/path/file.txt', 'r');

if ($fichier)
{

while (!feof($fichier)) // parcours de toutes les lignes.
{

$ligne = fgets($fichier); // ligne courante

echo $ligne; // afficher la ligne. ou faire autre chose ^^
}

fclose($fichier);
}
?>


P.S. : Bon pour ton cas, je viens de voir le site en question, c'est pas le plus évident ligne à ligne, surtout si ton fichier n'est en réalité qu'une seule ligne ... si tu peux insérer des retours à la ligne tout les 1000 décimales ... tu devrait t'en sortir avec ça .. autrement compliqué ..
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
190
merci beaucoup de proposer ton astuce. effectivement, c'est qu'une seule ligne dans mon fichier (une très très très grande ligne du coup), il y a pas de retour chariot. Il est évident que je peux pas mettre en mémoire tout le fichier d'un seul coup (même 1% du fichier) à chaque requête reçue.
je vais essayer ton idée mais avant de lire ligne par ligne, je vais d'abord lire caractère par caractère et voir si déjà il peut aller au delà de PHP_INT_MAX.
puis après j'évaluerais le gain de temps si je fais ligne par ligne en fonction de la taille de la ligne.
mais j'avouerai que si c'est pour faire ça, je préférerai autant choisir la solution de travailler avec plusieurs "petits" fichiers de 1 ligne chacun car je serai confronté à l'arrivée au même soucis dans le développement pour ma fonction de recherche de string.
Messages postés
1377
Date d'inscription
mercredi 18 mars 2009
Statut
Membre
Dernière intervention
5 mars 2020
190
bonsoir,

la Pi-Day est passée, les 17 milliards de décimales sont stockées sur le site et ça fonctionne à merveille.

la solution de la commande shell dd était pas mal mais relativement lente. j'ai opté le choix de faire plusieurs petits fichiers et de bien organiser mes scripts PHP. merci pour vos solutions qui m'ont été instructifs.

le lien du site si vous voulez vous amuser : http://www.piproject.org/decimals/ - il y a une appli android du site qui existe depuis samedi aussi (Decimals Search sur Google Play)

voilà j'arrête ma pub^^

merci encore!

Qui ne tente rien n'a rien