8791 sujets

Développement web côté serveur, CMS

Bonjour dans le cadre de mon travail je dois parser de gros fichiers régulièrement.
Ces fichiers peuvent contenir entre 700.000 et 1.500.000 lignes sous format edifact.

Quand je lis le fichier je dois le lire caractère par caractère car sinon les séparateurs ne sont pas visibles bref ce n'est pas vraiment problème (même si ca rallonge le temps d’exécution).

Mon problème est quand je lis le fichier entier ca met entre 5 et 10 minutes mais des que je traite les lignes qui m'intéressent je passe vite a des temps de 30 - 40 minutes pour le fichier.

Je comprend bien que vu que je rajoute un traitement ca ralonge le processus mais dans ce que je rajoute actuellement c'est qu'une infime partie du travail demander (Dans le code ci dessous je traite que 2 lignes sans rien faire dessus).

Est ce que vous avez des conseils pour augmenter la vitesse de traitement ? Utiliser Foreach au lieu de While ? Switch ou If ?

Toute aide est la bienvenue !

voici les deux fonctions principales de ma classe :


function read_file($file) {
		$handle = fopen($file, "r");
		$ligne = '';
		if($handle) {
			while(!feof($handle)) {
				$buffer = fgetc($handle);
				if($this->asc2bin($buffer) == '00011101') {
					$ligne .= '+';
				} else if($this->asc2bin($buffer) == '00011100') {
					//Fin de la ligne, on parse la ligne
					$this->read_line($ligne);
					//Reset de la ligne après son parsage
					$ligne = '';
				} else if($this->asc2bin($buffer) == '00011111') {
					$ligne .= ':';
				} else if($this->asc2bin($buffer) == '00011001') {
					$ligne .= '*';
				} else if($this->asc2bin($buffer) == '00001010') {
					$ligne .= '';
				} else {
					$ligne .= $buffer;
				}
				set_time_limit(30);
			}
			fclose($handle);
		}
	}
	
	//Parsage de la ligne
	function read_line($line) {
		$ligne = explode('+', $line);
		switch($ligne[0]) {
			case 'UNH':
				$this->compteur++;
			break;
			case 'UNZ':
				$this->show_line();
			break;
		}
	}

        function show_line() {
		$temps = microtime(true)-$this->time_in;
		echo $this->compteur.' messages dans le fichier (Execution en: '.$temps.')';
	}


Voici le temps que j'obtiens: 6115 messages dans le fichier (Execution en: 676.87485790253)
Administrateur
Bonjour,

un langage interprété comme le PHP est peut-être pas le plus indiqué ?
Je suis pas développeur mais dans le cadre d'un stage j'avais fait mumuse avec FLEX. Faut pas partir en courant à la vue du mot "lexical", c'est qu'un outil qui fait telle action dans tel contexte, compilé en C à partir du fichier *.lex
Après le souci serait de greffer ce programme avec ton code PHP sans ouvrir une faille béante de sécurité...
Disclaimer : "quand on a un marteau, tout ressemble à un clou" et flex est un outil que je connais mieux sans trop avoir d'expérience des autres outils, c'est donc un de mes marteaux Smiley cligne J'attendrais l'avis de vrais développeurs Smiley cligne
salut,

Utilise plutôt un switch, c'est plus efficace dans ce que tu fait.

ou soit, reste avec ta série de else if mais mets le résultat de l'objet que tu test dans une variable, ça devrait déjà aider un peu.
Modérateur
Et l'eau,

Comme l'a indiqué Felipe, parser de gros fichiers, PHP n'est peut être pas la meilleur solution. J'ai peut être une petite solution.

Est ce que la fonction file peut t'aider ? Après tu utilises le buffer de PHP pour lire caractère par caractère.