éditer un fichier texte

Petit nouveau ! | 6 Messages

26 févr. 2005, 17:27

Boujour à tous :D
c'est mon premier message alors je vais essayé d'être assez clair :lol:
je souhaite faire des statistiques pour mon site qui prendrait en compte les différents navigateur (de téléphone i-mode dans mon cas). Mais sans base de données, tout dans un fichier texte comme celui là:
Fichier istat.txt

Code : Tout sélectionner

n21i|0 web|0 n22i|0 n223i|0 n341i|0 m430i|0 n342i|0
Alors j'arrive à le lire mais le problème vient lorsque j'essaie de l'éditer (par exemple n21i|1). Entre 1 et 9 tout va bien mais dés que je suis à 10, le premier caractère de la ligne suivante est éffacé :? ...j'ai essayé de faire des décalage sur les caractères (cf "correction décimale") à partir de 10 mais en vain... :cry:
voici la partie du code qui ne va pas (la variable $tel est déjà detectée):
fichier stat.txt

Code : Tout sélectionner

//ouverture du fichier stat $fp = fopen("istat.txt","r+"); while(!feof($fp)) { $affich=explode("|",fgets($fp,4096)); if ( $affich[0]==$tel ) { $nouveau=$affich[1]+1 //correction decimale if ( $affich[1]<10 ) { $nb = 2; } elseif ( $affich[1]>=10 && $affich[1]<=99 ) { $nb = 3; } else { $nb = 4; } //positionement pointeur $ptr = ftell($fp); $ptr = fseek($fp,$ptr-$nb); fputs($fp,$nouveau."\n"); } } //on ferme le fichier fclose($fp);
vous auriez pas une idée?... :?:

ViPHP
ViPHP | 1380 Messages

26 févr. 2005, 18:34

Bonjour et bienvenue!

La manip des pointeurs me donne le tourni.

Alors, voici une solution différente qui utilise la fonction file() pour stocker ton fichier dans un tableau, éclater ce tableau sur '|' et rechercher la valeur cible.
// initialisation variables
$tab = file('test.txt');
$tel = 'n22i';
$string = null;
aff_tab($tab);

// construction du tableau
foreach ($tab as $v) $tab_explode[] = explode('|', $v);

// recherche de $tel et incrémentation. Reconstruction du fichier.
foreach ($tab_explode as $k=>$v){
  if ($v[0] == $tel){
    $tab_explode[$k][1] = ($tab_explode[$k][1]+ 1)."\n";
  }
  $string .= $tab_explode[$k][0].'|'.$tab_explode[$k][1];
}

// Ecriture du nouveau contenu
$fd = fopen('test.txt', 'w+');
fwrite($fd, $string);
fclose($fd);
Autre solution, plus courte, par regex. Contrairement aux idées reçues et au risque de me faire incendier, cette solution est souvent plus rapide pour faire une recherche sur de gros fichiers plats (je teste et je poste les résultats bientôt):
$txt = file_get_contents('test2.txt');
$motif = '#^('.$tel.'\|)(\d+)#me';
$string = preg_replace($motif, "'$1'.('$2'+1)", $txt);

// Ecriture du nouveau contenu
$fd = fopen('test2.txt', 'w+');
fwrite($fd, $string);
fclose($fd);
L'idéal, bien sûr, est d'utiliser MySql, mais j'imagine que si tu poses la question, c'est que tu ne veux ou ne peux pas y accéder...

Edit

Résultats du mini bench (fichier de 10.000 lignes):
0.097 sec. avec les fonctions file() et explode()
0.003 sec. avec regex
ripat

Petit nouveau ! | 6 Messages

27 févr. 2005, 02:15

merci bien, je vais essayer tout ça :wink:
edit:
je viens d'essayer avec regex et ça marche nikel :pouce:
Encore merci.

Par contre, pourrait-tu m'expliquer un peu cette ligne là:
$motif = '#^('.$tel.'\|)(\d+)#me';
je ne comprends pas trop :-k

ViPHP
ViPHP | 1380 Messages

27 févr. 2005, 10:50

Motif de concordance et de capture:

Code : Tout sélectionner

#^(n22i\|)(\d+)#me # délimiteur de motif ^ marque le début de la chaîne suivi par... (n22i\|) capture (#1) de la chaîne recherchée (variable $tel) suivie de | suivi par... (\d+) capture (#2) de tout nombre # délimiteur de motif m option m (pour que ^ soit appliqué à chaque nouvelle ligne) e option e pour l'interprétation du groupe replace plus loin
Remarque: l'ancrage ^ n'est pas indispensable mais accélère sensiblement le traitement de la regex car il diminue le nombre de possibilités (moins d'états intermédiaires, donc moins de backtracking pour le moteur regex)

Groupe de remplacement

Code : Tout sélectionner

"'$1'.('$2'+1)" ici on reconstruit la chaîne en incrémentant l'indice contenu dans capture 2 '$1' premier groupe de capture (n22i\|) suivi par... ('$2'+1) deuxième groupe (l'indice) plus 1
ripat

Petit nouveau ! | 6 Messages

27 févr. 2005, 20:47

merci beaucoup pour l'info
donc je suppose que si on a cette chaîne:

Code : Tout sélectionner

n22i|10|10122005
ça marche aussi:

Code : Tout sélectionner

^('.$tel.'\|)(\d+\|)('.$date.')#me
avec
capture1 $tel
capture2 nombre
capture3 $date

:?:

ViPHP
ViPHP | 1380 Messages

28 févr. 2005, 09:27

Presque. Car si tu mets le deuxième | (n22i|6|10122005 ) dans le capture #2 l'incrémentation ne se fera plus convenablement car php ne fera pas d'oprération mathématique sur ce qu'il prendra comme une chaîne de caractères (ou plutôt si, mais il supprimera le |). Il vaut donc mieux mettre le | dans le troisième capture qui est déjà une chaîne et sur laquelle, qui plus est, on ne fait pas de transformation.

Il ne faut pas non plus oublier de rajouter le capture#3 dans la groupe replace.
$motif = '#^('.$tel.'\|)(\d+)(\|'.$date.')#me';
$string = preg_replace($motif, "'$1'.('$2'+1).'$3'", $txt);
ripat

Petit nouveau ! | 6 Messages

28 févr. 2005, 19:47

ok, merci, j'ai tout compris :lol: