"preg_replace" dans un fichier texte

"preg_replace" dans un fichier texte - PHP - Programmation

Marsh Posté le 27-06-2006 à 13:30:01    

Salut tout le monde !  
 
J'ai besoins de créer une fonction PHP qui agisse comme un preg_replace, mais dans un fichier texte préalablement ouvert en mode r+ (lecture et écriture). J'ai cherché un peu sur Google et sur ce forum, et je n'ai rien trouvé..  
 
Il se trouve que j'ai deux gros problèmes dans la conception de ma fonction :  
 
Le premier est au niveau des CHMOD. A chaque fois que j'upload mon fichier texte dans lequel je vais effectuer mon preg_replace, les droits d'accès redeviennent 0644. Or pour que ma fonction puisse écrire dans le fichier, je voudrais mettre les droits d'accès du fichier à 0666, puis les remettre à 0644 à la fin de ma fonction. Mais j'obtiens des Warnings du genre :  
Warning: chmod(): Operation not permitted in /home/www/...../tools/files.class.php on line 61
Pourtant je suis les recommandations de l'aide technique de mon hébergeur.  
 
Mon deuxième problème est au niveau de l'algorithme. Ma fonction a l'air de fonctionner, uniquement pour un fichier d'une seule ligne, et seulement lorsque la chaine qui remplace est plus longue que la chaine qu'on remplace.  
Il y a donc deux problèmes dans l'algorithme :  
- Si le mot qui remplace est plus court : dans ce cas, je vais essayer de faire une fonction qui supprime la chaine à remplacer, puis qui replace le curseur à l'endroit où on va insérer la chaine.  
- S'il y a plusieurs lignes dans le fichier texte : je ne vois pas trop où est le problème là.. Mon while est sencé traiter le fichier ligne par ligne jusqu'à la fin du fichier..  
 
 
Voici ma fonction :  
(Elle est dans une classe de gestion de fichiers.  
$this->filePointer est le pointer sur le fichier ouvert.  
$this->fileCurseur est le curseur interne dans le fichier.  
$this->fileName est l'adresse et le nom du fichier, ici "essai.txt".  
Le fichier est préalablement ouvert en mode r+. (Je viens de penser : peut-être que le fichier doit être fermé pour qu'on puisse utiliser chmod ?)

Code :
  1. function pregReplaceFile($modele,$remplacant)
  2.  {
  3.   // précondition : fichier ouvert.  
  4.   fseek($this->filePointer,0); // On remet le curseur en début de fichier.  
  5.   $old = umask(0000);
  6.   chmod($this->fileName,0666);
  7.   umask($old);
  8.   $this->fileCurseur = @ftell($this->filePointer); // Ca vaut 0, mais dans le doute, je le recalcule.  
  9.   while($source = @fgets($this->filePointer)) // On parcourt le fichier ligne par ligne (parce visiblement,  
  10.              //on ne peut pas avoir tout le fichier dans une chaine ?)
  11.    {
  12.     echo "<br>source : ".$source;
  13.     if($resultat=preg_replace($modele,$remplacant,$source))
  14.      {
  15.       // Si on trouve le modèle, on remplace.  
  16.       fseek($this->filePointer,$this->fileCurseur);
  17.       fputs($this->filePointer,$resultat);
  18.       echo "<br>Resultat : ".$resultat;
  19.      }
  20.     $this->fileCurseur = ftell($this->filePointer);
  21.     $source=""; // inutile.  
  22.    }
  23.   echo "<br>FIN";
  24.   chmod($this->fileName,0644);
  25.  }


 
 
Voici le contenu de mon fichier de test "essai.txt" :  

Code :
  1. Je m'appelle : [NOM] !!
  2. Bonjour [NOM]...


 
Et l'appel à la fonction pregRepaceFile :  

Code :
  1. $essai = new files("essai.txt" );
  2. $essai->openFile("r+" );
  3. $essai->pregReplaceFile("`\[NOM\]`","Triphon Tournessol" );


 
 
Cela affiche :  

Code :
  1. Warning: chmod(): Operation not permitted in /home/www/..../tools/files.class.php on line 61
  2. source : Je m'appelle : [NOM] !!
  3. Resultat : Je m'appelle : Triphon Tournessol !!
  4. source : ...
  5. Resultat : ...
  6. FIN
  7. Warning: chmod(): Operation not permitted in /home/www/..../tools/files.class.php on line 77


 
et le fichier essai.txt contient :  

Je m'appelle : Triphon Tournessol !!
...


 
 
 
 
 
 
Voila, donc est-ce que vous pourriez me donner quelques conseils ? En créeant une fonction qui efface d'abord la chaine recherchée dans le fichier, j'ai peur de m'enfoncer dans quelque chose de trop lourd. Je veux un programme léger, et peut-être que sans le savoir, je m'enmerde pour rien, et qu'une fonction de type preg_replace existe déjà pour les fichiers.. Mais je ne la connais pas... Merci pour votre aide !
 
 
EDIT : Sinon, est-ce que ça ne serait pas plus simple de récupérer tout le fichier sous forme d'un tableau des lignes du fichier, de concatener chaque ligne du tableau, de faire un ereg_replace sur cette grosse chaine, et de remplacer le contenu du fichier texte par la chaine qu'on vient de fabriquer ? J'ai peur que ce soit lourd. Mon but est vraiment de faire la fonction la plus simple et la plus légère possible. Je ne sais pas si 1 preg_replace sur chaque ligne d'un fichier de 1000 lignes (ça fait 1000 appels à preg_replace) est plus long que 1 preg_replace sur une grosse chaine qui représente un fichier de 1000 lignes...


Message édité par Docteur_Cube le 27-06-2006 à 14:17:00
Reply

Marsh Posté le 27-06-2006 à 13:30:01   

Reply

Marsh Posté le 27-06-2006 à 14:41:30    

Yop...

Citation :

Sinon, est-ce que ça ne serait pas plus simple de récupérer tout le fichier sous forme d'un tableau des lignes du fichier, de concatener chaque ligne du tableau, de faire un ereg_replace sur cette grosse chaine, et de remplacer le contenu du fichier texte par la chaine qu'on vient de fabriquer ?


 
Bon là je pense que t'est parti du mauvais coté dès le début, si je ne me trompe pas, au d'essayer d'utiliser des regex sur le contenu d'un fichier ce qui, que je sache, n'existe pas. Ce que je ferais c'est :
- ouvrir le fichier
- récupérer son contenu dans une chaîne de caractères : file_get_contents(...)
- effectuer le traitement voulu : preg_replace(...)
- enregistrer le nouveau contenu
 
perso, ça me semble plus réaliste que tout le bazar à faire en touchant aux chmods... maintenant je suis pas un expert au niveau optimisation sur les lectures de fichier/ grosse chaines en PHP je me rapelle avoir lu, dans les sources ou la doc que "la taille des chaines n'est pas un problème", sans plus de précision.

Reply

Marsh Posté le 27-06-2006 à 14:58:24    

Bon, finalement je me suis débrouillé tout seul ^^. Mais ce que j'ai fais, c'est du bricolage.. Je suis sûr que c'est très lourd, et j'aimerais vraiment que vous m'aidiez à l'optimiser un peu. Je n'ai pas assez d'expérience en PHP pour savoir ce qui est plus avantageux d'utiliser.  
 
Voici ma fonction, qui marche :  
 

Code :
  1. function pregReplaceFile($modele,$remplacant)
  2.  {
  3.   // précond : fichier fermé.   
  4.   $this->openFile("r" );
  5.   $this->chainFile();
  6.   $this->fileChain = preg_replace($modele,$remplacant,$this->fileChain);
  7.   $this->closeFile();
  8.   unlink($this->fileName);
  9.   copy("null",$this->fileName);
  10.   chmod($this->fileName,0666);
  11.   $this->openFile("r+" );
  12.   fputs($this->filePointer,$this->fileChain);
  13.   $this->fileChain="";
  14.   $this->closeFile();
  15.  }


 
$this->chainFile met le contenu du fichier sous la forme d'une chaine de caractères dans la variable $this->fileChain.  

Code :
  1. function chainFile()
  2.  {
  3.   // précond : fichier ouvert.  
  4.   @fseek($this->filePointer,0);
  5.   $this->tabFile(); // Fonction identique à file.  
  6.   for($i=0;$i<count($this->fileTab);$i++)
  7.    {
  8.     $this->fileChain .= $this->fileTab[$i];
  9.    }
  10.  }


 
null est un fichier qui ne contient qu'un espace (qui est effacé par n'importe quelle chaine d'au moins 1 caractère ensuite).  
J'ai utilisé cette méthode car je ne sais pas comment faire pour créer directement un fichier.  
Le problème de cette fonction, c'est qu'elle oblige à ouvrir et fermer plusieurs fois un fichier, ce qui n'est pas trop le but de ma classe de gestion d'un fichier (car elle est censé gérer un seul fichier ouvert préalablement).  
Si vous pouvez m'aidez à l'améliorer, ce serait sympa !
 
 
 
EDIT : randiox, je viens de voir ton message. Je vais essayer avec file_get_contents ! Est-ce que tu sais s'il existe une fonction pour vider un fichier, ou pour en créer un ?
EDIT : ça y est, ça marche avec file_get_contents ! Merci beaucoup pour cette fonction. Par contre, je suis toujours obligé d'ouvrir et de fermer deux fois mon fichier dans la fonction.. Et je suis obligé aussi d'utiliser chmod ici.


Message édité par Docteur_Cube le 27-06-2006 à 15:12:50
Reply

Marsh Posté le 27-06-2006 à 15:35:26    

Yop,
hum... à ma connaissance, le seul moyen pour créer un fihier c'est la fonction fopen()... avec le bon argument :
 

Citation :

'w'  Ouvre en écriture seule ; place le pointeur de fichier au début du fichier et réduit la taille du fichier à 0. Si le fichier n'existe pas, on tente de le créer.


par exemple...
 
En fait la pluspart de tes questions trouverons une réponse ici :
http://fr2.php.net/manual/fr/ref.filesystem.php
 
bonne lecture


Message édité par randiox le 27-06-2006 à 15:35:41
Reply

Marsh Posté le 27-06-2006 à 16:19:54    

Ha oui merci beaucoup pour fopen avec "w". J'avais complètement oublié que ça créeait le fichier s'il n'existe pas. Je pense que je vais utiliser ça pour ma fonction. C'est un peu plus propre que d'utiliser un fichier vide.  
 
Donc, voila à quoi ressemble ma fonction maintenant :  
 

Code :
  1. function pregReplaceFile($modele,$remplacant)
  2.  {
  3.   // précondition : fichier fermé.   
  4.   $this->openFile("r" );
  5.   $this->chainFile();
  6.   $this->fileChain = preg_replace($modele,$remplacant,$this->fileChain);
  7.   $this->closeFile();
  8.   unlink($this->fileName);
  9.   $this->openFile("w" );
  10.   fputs($this->filePointer,$this->fileChain);
  11.   $this->fileChain="";
  12.   $this->closeFile();
  13.   chmod($this->fileName,0666);
  14.  }


 
Et à première vue ça marche aussi si $modele et $remplacant son dont des tableaux, mais je n'ai pas encore testé.  
C'est vraiment génial en tout cas ! Cette fonction marche exactement comme je le souhaitais.  
Merci pour ton aide randiox.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed