Précision sur l'import d'un fichier texte avec file()

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Précision sur l'import d'un fichier texte avec file()

par rspir » 05 nov. 2006, 18:08

Ce qui pourrait me permettre de lire mon fichier et d'en récupérer le contenu par bloc de 1000 lignes ?

par Ajoloca » 03 nov. 2006, 01:04

Bonsoir,

La fonction fread() est la version binaire de fgets(), ce qui veux dire que le caractère de fin de ligne est un octet comme un autre et ne l'interprète pas en tant que tel.

La fonction fgets(), elle, elle lit un block d'octets determiné par le second paramètre - 1 (si pas de paramètre la valeur par défaut est 1024), à moins qu'elle ne rencontre un caractère de fin de ligne ou fin de fichier avant d'atteindre le nombre d'octets.

Ce qui veux dire que fgets() peux lire ligne par ligne à condition que nombre d'octets (second paramètre) soit supérieur à la longueur de la ligne (caractère de fin y compris)

Les fonctions ftell() et fseek() peuvent être utiles dans le cas ou l'on souhaite se "ballader" dans un fichier.

par rspir » 03 nov. 2006, 00:43

Ce qui était simple avec file(), c'était que chaque ligne correspondait à un enregistrement dans le tableau.

Avec fread(), je ne vois pas trop comment je vais faire : la longueur de chaque enregistrement n'étant pas fixe. Je connais la longueur max. de chaque enregistrement mais fread détecte t'il le changement de ligne ?

par Ryle » 02 nov. 2006, 18:03

Bah non en fait, ma suggestion supposait que tu parvenais à parser le fichier ...
As tu essayer de remplacer le file() par un fopen() et fread() pour bufferiser la lecture du fichier ? Je ne sais pas du tout si peut avoir un impact ou non sur l'occupation des ressources, mais ça coute pas grand chose d'essayer :)

par rspir » 02 nov. 2006, 17:26

Oui effectivement, j'ai au quelques souci en faisant mon post.
J'ai corrigé les erreurs.

Pour ce qui est de la limitation mémoire, je voens de constater que le pb survenait dès la ligne
	$content=file("source/pdv.txt");
Donc dans tous les cas le "for" ou "foreach" n'est pas le pb. Il faudrait que j'arrive à ne lire qu'une partie du fichier.
Le souci est que file répondait bien à mon besoin initial.
Ou alors je découpe mon fichier texte en 2 avec un script dos ou autre. Mais la je ne sais pas faire.

Qu'entends tu par
Sinon, une autre solution pourrait être de constituer un fichier csv (séparateur ";") à partir de ton fichier bloc et de le charger directement dans ta base avec un loader ?
Plus précisément, je ne vois pas comment faire un un fichier csv à partir du fichier bloc compte tenu de la limitation mémoire que j'ai à gérer.

par Ryle » 02 nov. 2006, 17:19

Dans le cas d'un tableau non associatif, le foreach() n'est qu'une manière simplifiée d'écrire le for(), retournant du premier au dernier élément de ton tableau. Ces deux méthodes reviennent au même (pour un tableau indexé) :
foreach($tableau as $ligne) {
  ...
}

for ($i=0; $i<count($tableau); $i++) {
  $ligne = $tableau[$i];
  ...
}
A noter que tu as deux foreach, si c'est pas une erreur de retranscription, ça ne fera pas de mal à ton code d'en retirer un ;)
Y a également je pense une erreur dans les noms des champs "c13c,14" de ta requête

Sinon, une autre solution pourrait être de constituer un fichier csv (séparateur ";") à partir de ton fichier bloc et de le charger directement dans ta base avec un loader ?
Enfin il me semble que quelqu'un avait fait des tests de perf dernièrement sur le insert et avait constaté qu'un seul insert étendu (avec toutes les lignes à insérer) était nettement plus performant que quelques centaines d'insert consécutifs... à voir si tu le retrouves en cherchant dans le forum... :)

Précision sur l'import d'un fichier texte avec file()

par rspir » 02 nov. 2006, 16:59

Bonjour à tous

Je souhaiterais avoir des conseils pour optimiser un import de fichier texte.
Actuellemment j'ai un script qui repose sur la commande file() pour importer dans une table les données d'un fichier texte plat.
	$content=file("source.txt");	
	foreach($content as $num=>$ligne)
	{
                 $var1=substr($ligne,0,8);
                 $var2=substr($ligne,8,8);
                 $var3=substr($ligne,16,17);
                 $var4=substr($ligne,33,8);
                 $var5=addslashes(substr($ligne,41,128));
                 $var6=substr($ligne,169,8);
                 $var7=addslashes(substr($ligne,177,128));
                  $var8=addslashes(substr($ligne,305,32));
                  $var9=substr($ligne,337,5);
                  $var10=substr($ligne,342,32);
                  $var11=substr($ligne,374,3);
                  $var12=substr($ligne,377,11);
                  $var13=substr($ligne,507,1);
                  $var14=substr($ligne,508,1); 	
	
	  $requete = "INSERT INTO matable (c1, c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13,c14) VALUES
('$var1','$var2','$var3','$var4','$var5','$var6','$var7','$var8','$var9','$var10','$var11','$var12','$var13','$var14')";
	ExecRequete ($requete, $connexion);
              }
Tout fonctionnait à merveille, cependant mon admin système a du (pour des raisons techniques autres) limiter les process mémoire.
Du coup, importer mon fichier n'est plus possible compte tenu de la taille de mon fichier texte.

Je me demandais, si je pouvais contourner en important par bloc de 1000 lignes par exemple.

Simplement, je ne vois pas comment faire ca à à cchaque fois que je vois al commande file(), je vois la commande foreach qui importe toutes les lignes.

Y'a til un moyen de remplacer le foreach de manière à importer 1000 lignes. Et de faire une boucle pour commencer à la ligne 1 puis reprendre à la 1001 etc .. ?

Ou faut t'il que je travaille totalement différemment ?

Merci d'avance de vos recommandations