Précédent   Forum des professionnels en informatique > PHP > Langage > Fonctions
Fonctions Forum d'entraide sur les fonctions PHP. Avant de poster -> FAQ fonctions et Sources diverses
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 27/04/2011, 10h54   #1
Invité de passage
 
Inscription : avril 2010
Messages : 35
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 35
Points : 4
Points : 4
Par défaut double boucle fopen() sur même fichier ?

Bonjour à tous !

Voilà, je poste pour une petite question, qui est à l'origine un problème que j'essaie de résoudre.
J'ai un script qui lit un fichier .txt afin d'en extraire des informations et de modifier une base de données : ajouter ou mettre à jour des entrées.

Le fichier, globalement, ce sont des données ligne par ligne, séparées par un point-virgule. Il fait 70Mo, mais je ne pense pas que ce soit le problème.
Pour certaines raisons, je dois faire une double boucle sur le même fichier.
Je me demandais donc si faire deux fopen() sur le même fichier à la suite, sans fclose entre deux, avec deux variables différentes pour le $handle, pouvait faire planter le script, à cause de permissions ou de choses comme ça par exemple.

Car mon script se termine, je ne sais même pas pourquoi, et pour couronner le tout je n'ai pas accès aux logs PHP (hébergement OVH mutualisé) et l'affichage des erreurs PHP sur la page (E_ALL) ne donne rien.

Bref, est-ce que le script se termine à cause de ces permissions, ou est-ce un autre problème ?

Voici le script, au cas où :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 
 
<?PHP
include("../inc/header_admin.php");
 
// Activer le rapport d'erreurs PHP
if ($_SERVER['SERVER_NAME'] == "localhost" )  error_reporting(E_ALL);
 
$fichier = fopen("../maj_dossier/EXPARTHQ.txt", "r");
 
while (($tableau_chaine = fgetcsv($fichier,1024,";")) !== FALSE)
{
	echo "Première boucle : OK.";
	//$tableau_chaine = fgetcsv($fichier,1024,";");
 
	if ($tableau_chaine[0]=="ARTMAG" && $tableau_chaine[4]=="10")
	{
		echo "Produit du magasin 10 !";
		$code_article=sprintf("%s %s %s",$tableau_chaine[1],$tableau_chaine[2],$tableau_chaine[3]);
		//$quantite=$tableau_chaine[5];
/***********************************************************************************/
 
		fclose($fichier);
		$fichier2 = fopen("../maj_dossier/EXPARTHQ.txt", "r");
 
		while (($tableau_chaine2 = fgetcsv($fichier2,1024,";")) !== FALSE)
		{
			echo "Deuxième boucle : OK.";
			//$tableau_chaine2 = fgetcsv($fichier2,1024,";");
 
			if ($tableau_chaine2[0]=="ARTICLE" && $tableau_chaine2[1]==$tableau_chaine[1] && $tableau_chaine2[2]==$tableau_chaine[2] && $tableau_chaine2[3]==$tableau_chaine[3])
			{	
				$prix=$tableau_chaine2[17];
				$description=addslashes($tableau_chaine2[5]);
				$description2=addslashes($tableau_chaine2[6]);
 
				echo "Code article : ".$code_article."<br />";
				//echo "Quantite : ".$quantite."<br />";
				echo "Description : ".$description."<br />";
				echo "Description 2 : ".$description2."<br />";
				echo "Prix : ".$prix."<br />";
 
				$sql_compte = sprintf("SELECT COUNT(*) FROM types_produits WHERE ref_produit='%s'",$code_article);
				$requete_compte = mysql_query($sql_compte);
				if (!$requete_compte)
				{
					die('Requete invalide : ' . mysql_error());
				}
				if ($donnees_compte = mysql_fetch_array($requete_compte))
				{
					$nombre_enregistrement = $donnees_compte['COUNT(*)'];
					//$selection = $donnees_compte['selection'];
					echo "Nombre enregistrement : ".$nombre_enregistrement."<br />";
					//echo "Selection : ".$selection."<br />";				
 
 
					//$nouvelle_quantite=$selection+$quantite;
 
					if ($nombre_enregistrement==0)
					{
						$requete="INSERT INTO types_produits (ref_produit, marque, sous_marque, prix_u) VALUES ('$code_article','$description','$description2','$prix')";
						$execution = mysql_query($requete);
						if (!$execution) {
							die("Erreur d execution :".mysql_error());
						}
					}
					else
					{
						$requete="UPDATE types_produits SET prix_u='$prix' WHERE ref_produit='$code_article'";
						$execution = mysql_query($requete); 
						if (!$execution) {
							die("Erreur d execution :".mysql_error());
						}
					}
				}
			}
		}
		echo "Fin du fichier ARTICLE <br />";
		echo "**************************<br />";
		fclose($fichier2);
/***********************************************************************************/
	}
}
echo "Fin du fichier ARTMAG <br />";
fclose($fichier);
/**************************************/
echo "<center><br /><a href='../administration/accueil_admin.php'>Retour</a></center>";
 
include("../inc/footer_admin.php");
?>
En gros quand je dis que le script ne se termine pas, je veux dire que la phrase "Fin du fichier ARTMAG", à la fin, ne s'affiche pas.

Merci d'avance !
.Spirit est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 11h14   #2
Rédacteur/Modérateur
 
Avatar de MaitrePylos
 
Homme Gérard Ernaelsten
DBA & Dev PHP
Inscription : juin 2005
Messages : 3 174
Détails du profil
Informations personnelles :
Nom : Homme Gérard Ernaelsten
Âge : 39
Localisation : Belgique

Informations professionnelles :
Activité : DBA & Dev PHP
Secteur : Service public

Informations forums :
Inscription : juin 2005
Messages : 3 174
Points : 6 460
Points : 6 460
Cela ne serais pas plus en cause la durèe du script qui dépasse 30 secondes ?
MaitrePylos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 11h24   #3
Membre Expert
 
Inscription : avril 2006
Messages : 1 338
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : avril 2006
Messages : 1 338
Points : 1 315
Points : 1 315
+1 Maitre pylos.

Ça ne serait pas possible de procéder autrement plutôt que d'ouvrir plusieurs fois le même fichier?
__________________
Stay in Bed .. Save Energy
boo64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 14h27   #4
Invité de passage
 
Inscription : avril 2010
Messages : 35
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 35
Points : 4
Points : 4
Merci pour votre réponses !

Si, je l'ai compris après, c'est pourquoi je venais répondre à mon post
Le script est arrêté par OVH car justement c'est un hébergement mutualisé.

Je suis en train de reformer le script afin de n'effectuer qu'une seule boucle, mais pas facile. Pour l'instant ça marche... avec une ligne sur deux. Je sais pourquoi mais pas comment le résoudre pour le moment.

Le problème est que je teste si on arrive à telle ligne (en l'occurence une ligne qui commence par ARTICLE) afin de sortir de ma boucle, mais j'ai besoin de lire cette ligne ensuite dans ma la boucle de plus haut niveau. Donc je saute une ligne sur deux.

En gros il me faudrait un truc qui me permettre de remonter le pointeur de fichier d'une ligne, mais ça ne doit pas être possible de procéder ainsi...

Voici le code :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
 
<?PHP
include("../inc/header_admin.php");
 
echo "Mise à jour numero 1.<br />";
 
// Activer le rapport d'erreurs PHP
if ($_SERVER['SERVER_NAME'] == "localhost" )  error_reporting(E_ALL);
 
$fichier = fopen("../maj_dossier/EXPARTHQ2.txt", "r");
 
while (($tableau_chaine = fgetcsv($fichier,1024,";")) !== FALSE)
{
	//echo "Première boucle : OK.";
	//$tableau_chaine = fgetcsv($fichier,1024,";");
 
	if ($tableau_chaine[0]=="ARTICLE")
	{
		//$tableau_chaine2[0] = "";
		$flag_eof = ($tableau_chaine2 = fgetcsv($fichier,1024,";"));
		while($tableau_chaine2[0] != "ARTICLE" && $flag_eof !== FALSE) {
			if($tableau_chaine2[0] == "ARTMAG" && $tableau_chaine2[4] == "10") {
				if($tableau_chaine2[1]==$tableau_chaine[1] && $tableau_chaine2[2]==$tableau_chaine[2] && $tableau_chaine2[3]==$tableau_chaine[3]) {
					$code_article = sprintf("%s %s %s",$tableau_chaine2[1],$tableau_chaine2[2],$tableau_chaine2[3]);
 
					$prix=$tableau_chaine[17];
					$description=addslashes($tableau_chaine[5]);
					$description2=addslashes($tableau_chaine[6]);
 
					echo "Code article : ".$code_article."<br />";
					//echo "Quantite : ".$quantite."<br />";
					echo "Description : ".$description."<br />";
					echo "Description 2 : ".$description2."<br />";
					echo "Prix : ".$prix."<br />";
 
					$sql_compte = sprintf("SELECT COUNT(*) FROM types_produits WHERE ref_produit='%s'",$code_article);
					$requete_compte = mysql_query($sql_compte);
					if (!$requete_compte)
					{
						die('Requete invalide : ' . mysql_error());
					}
					if ($donnees_compte = mysql_fetch_array($requete_compte))
					{
						$nombre_enregistrement = $donnees_compte['COUNT(*)'];
						//$selection = $donnees_compte['selection'];
						echo "Nombre enregistrement : ".$nombre_enregistrement."<br />";
						//echo "Selection : ".$selection."<br />";				
 
 
						//$nouvelle_quantite=$selection+$quantite;
 
						if ($nombre_enregistrement==0)
						{
							$requete="INSERT INTO types_produits (ref_produit, marque, sous_marque, prix_u) VALUES ('$code_article','$description','$description2','$prix')";
							$execution = mysql_query($requete);
							if (!$execution) {
								die("Erreur d execution :".mysql_error());
							}
						}
						else
						{
							$requete="UPDATE types_produits SET prix_u='$prix' WHERE ref_produit='$code_article'";
							$execution = mysql_query($requete); 
							if (!$execution) {
								die("Erreur d execution :".mysql_error());
							}
						}
					}
					echo "Fin de l'ARTICLE <br />";
					echo "**************************<br />";
				}
			}
		}
	}
}
echo "Fin du fichier ARTMAG <br />";
fclose($fichier);
 
 
echo "<center><br /><a href='../administration/accueil_admin.php'>Retour</a></center>";
 
include("../inc/footer_admin.php");
?>
Le code est déjà un peu plus simple, je sens que je suis près du but !

Merci à vous en tout cas, si j'ai la solution je la posterai.
.Spirit est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 14h33   #5
Membre Expert
 
Inscription : avril 2006
Messages : 1 338
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : avril 2006
Messages : 1 338
Points : 1 315
Points : 1 315
Si tu precise plus le besoin général on pourra peut-être mieu t'aider.

le bout de code est une xtrait ou tu n'as besoin de récuperer que des éléments ARTMAG:

Code :
if($tableau_chaine2[0] == "ARTMAG" && $tableau_chaine2[4] == "10"
__________________
Stay in Bed .. Save Energy
boo64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 14h57   #6
Membre Expert
 
Inscription : avril 2006
Messages : 1 338
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : avril 2006
Messages : 1 338
Points : 1 315
Points : 1 315
Sinon un script plus simplifié :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$fichier = fopen("../maj_dossier/EXPARTHQ2.txt", "r");
$IsArticle = false;
$nombre_enregistrement;
$code_article = null;
while (($tableau_chaine = fgetcsv($fichier,1024,";")) !== FALSE){
	//nouvelle article
	if ($tableau_chaine[0]=="ARTICLE"){
		$code_article = sprintf("%s %s %s",$tableau_chaine2[1],$tableau_chaine2[2],$tableau_chaine2[3]);
		$sql_compte = sprintf("SELECT COUNT(*) FROM types_produits WHERE ref_produit='%s'",$code_article);
		$requete_compte = mysql_query($sql_compte) or die('Requete invalide : ' . mysql_error());
		$donnees_compte = mysql_fetch_row($requete_compte);
		$nombre_enregistrement = $donnees_compte[0];
	}
	else if($code_article != null && $tableau_chaine[0] == "ARTMAG" && $tableau_chaine[1].$tableau_chaine[2].$tableau_chaine[3] == $code_article && $tableau_chaine[4] == "10") {
 
		$prix=$tableau_chaine[17];
		$description=addslashes($tableau_chaine[5]);
		$description2=addslashes($tableau_chaine[6]);
 
		echo "Code article : ".$code_article."<br />";
		//echo "Quantite : ".$quantite."<br />";
		echo "Description : ".$description."<br />";
		echo "Description 2 : ".$description2."<br />";
		echo "Prix : ".$prix."<br />";
		if ($nombre_enregistrement==0)
		{
			$requete="INSERT INTO types_produits (ref_produit, marque, sous_marque, prix_u) VALUES ('$code_article','$description','$description2','$prix')";
		}
		else
		{
			$requete="UPDATE types_produits SET prix_u='$prix' WHERE ref_produit='$code_article'";
		}
		$execution = mysql_query($requete) or die("Erreur d execution :".mysql_error());
	}
}
ce qui me dérange c'est que avec un même fichier d'import tu vas update plusieurs fois type_produits pr le même code produit non?
__________________
Stay in Bed .. Save Energy
boo64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 14h57   #7
Rédacteur/Modérateur
 
Avatar de MaitrePylos
 
Homme Gérard Ernaelsten
DBA & Dev PHP
Inscription : juin 2005
Messages : 3 174
Détails du profil
Informations personnelles :
Nom : Homme Gérard Ernaelsten
Âge : 39
Localisation : Belgique

Informations professionnelles :
Activité : DBA & Dev PHP
Secteur : Service public

Informations forums :
Inscription : juin 2005
Messages : 3 174
Points : 6 460
Points : 6 460
Et dans un premier temps si tu augmentais le temps d'attente d'un script

Code :
1
2
3
 
//a mettre au début du script
ini_set('max_execution_time',300 ); //5 minutes
MaitrePylos est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 15h01   #8
Invité de passage
 
Inscription : avril 2010
Messages : 35
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 35
Points : 4
Points : 4
En gros le fichier se présente comme ça :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
ARTICLE;XXX;XX;XX;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;01;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;02;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;03;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;04;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;05;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;06;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;07;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;08;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;09;...;...;...;...;...;...;...;...;
ARTMAG;XXX;XX;XXX;10;...;...;...;...;...;...;...;...;
Il y a un article, vendu dans plusieurs magasins (mais pas toujours tous).
Je ne m'intéresse qu'au magasin 10.
Avant la moulinette cherchait une ligne ARTMAG donc le code magasin était 10, et refaisait une boucle pour trouver la ligne ARTICLE identifiée par son code article (les données marquées par des XXX;XX;XXX).

J'ai modifié ce script pour permettre de ne faire qu'une seule boucle, donc maintenant je recherche d'abord la ligne ARTICLE, et j'exécute le code seulement si la ligne ARTMAG avec le numéro 10 suit (comme dans l'exemple ci-dessus).

Le problème est que ma boucle permettant de rechercher cette ligne ARTMAG s'arrête quand elle trouve une ligne ARTICLE (l'article suivant). Donc je reviens dans une boucle de plus haut niveau (celle qui cherche les lignes ARTICLE). Le truc c'est que comme le pointeur a déjà passé la ligne article (à cause du while de plus bas niveau), je loupe un article sur deux.

Voilà pour les explications :p
J'ai volontairement mis les données en "XXX" ou "..." car je ne sais pas si j'ai le droit de divulguer ça. Bref, ça ne pose pas de problème de toute manière.

Merci !


Edit : bon j'ai l'air d'avoir trouvé. Sauf qu'apparemment le script est toujours trop long et dépasse les 30 secondes. 70Mo le fichier texte quand même ! Je dois lire toutes les lignes.
Je ne sais pas trop comment faire...

Je pense qu'en attendant je vais rapatrier la base de données sur mon ordinateur, la mettre à jour et réimporter la base, je ne vois que ça.
.Spirit est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 15h24   #9
Membre Expert
 
Inscription : avril 2006
Messages : 1 338
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : avril 2006
Messages : 1 338
Points : 1 315
Points : 1 315
donc mon code devrais te convenir
__________________
Stay in Bed .. Save Energy
boo64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 15h39   #10
Invité de passage
 
Inscription : avril 2010
Messages : 35
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 35
Points : 4
Points : 4
@Maître Pylos : j'ajoute ton code et je teste, mais il me semble que chez OVH ça ne fait rien. Je tente quand même.

@Boo64 : A première vue, ton code ne lie pas ARTICLE et ARTMAG, si ?
Ce que je veux faire, c'est, si une ligne ARTMAG avec le code magasin 10 existe, alors je vais rechercher la ligne ARTICLE correspondante (via le code article en trois parties commun aux deux lignes ARTMAG et ARTICLE) afin de récupérer les informations comme la description, le prix, etc...

Merci à vous deux en tout cas, c'est sympa de m'aider.

edit : ah non je vois ce que tu veux dire Boo ! Je teste ça de suite
.Spirit est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 16h04   #11
Invité de passage
 
Inscription : avril 2010
Messages : 35
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 35
Points : 4
Points : 4
Bon ben j'ai testé le script, il fonctionne (avec quelques adaptations car tu n'as pas pu tester de ton côté donc c'est normal ), sauf que... toujours pas sur le gros fichier.

Je pense que lire le fichier ligne par ligne n'est donc pas la bonne solution, on a fait le tour des manières de coder ce truc !
Je pense me pencher vers une migration de la base vers ma machine locale, sa mise à jour, puis une restauration de la base en ligne.
Ceci dit, c'est pas très automatisé, mais la mise à jour n'a lieu que deux fois par ans.

C'est ça ou prendre un dédié chez OVH, AMHA.

Qu'en pensez-vous ?
.Spirit est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 16h09   #12
Membre Expert
 
Inscription : avril 2006
Messages : 1 338
Détails du profil
Informations personnelles :
Localisation : France, Haute Garonne (Midi Pyrénées)

Informations forums :
Inscription : avril 2006
Messages : 1 338
Points : 1 315
Points : 1 315
Citation:
Envoyé par MaitrePylos Voir le message
Et dans un premier temps si tu augmentais le temps d'attente d'un script

Code :
1
2
3
 
//a mettre au début du script
ini_set('max_execution_time',300 ); //5 minutes
sinon :
http://travaux.ovh.net/?do=details&id=5332
__________________
Stay in Bed .. Save Energy
boo64 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/04/2011, 16h33   #13
Modérateur
 
Inscription : septembre 2010
Messages : 7 103
Détails du profil
Informations forums :
Inscription : septembre 2010
Messages : 7 103
Points : 8 466
Points : 8 466
tu devrais faire ca en 2 temps

- traiter le CSV (et le mettre tout ca dans un nouveau CSV)
- inséré le nouveau CSV

sinon t'as mysqli ou PDO ? même sans avoir les 2 tu peux toujours faire une requête préparée qui sera dans ton cas plus efficace

EDIT : quelque chose dans le style https://gist.github.com/944414
__________________
http://blog.stealth35.com/
stealth35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/04/2011, 10h48   #14
Invité de passage
 
Inscription : avril 2010
Messages : 35
Détails du profil
Informations forums :
Inscription : avril 2010
Messages : 35
Points : 4
Points : 4
Salut,

Finalement, il semble que depuis le logiciel qui exporte ce gros fichier on puisse sélectionner ce qu'il faut importer. Car dans ce fichier de 70 Mo, 75% des lignes ne me servent pas, mais sont quand même lues par le script.

La base de données a été mise à jour pour finir (je suis passé par le local, en attendant).

Je vais tout de même étudier ton script stealth. Merci bien !
.Spirit est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 08h08.


 
 
 
 
Partenaires

Hébergement Web