Lire un fichier ligne par ligne

Résolu
Utilisateur anonyme - 23 mai 2008 à 21:21
 Utilisateur anonyme - 24 mai 2008 à 18:00
Bien le bonjour, je me suis fait un 'tit bou de code afin de lire un fichier texte ligne par ligne.

Je voulais juste savoir si il avait des améliorations encore a faire ou pas (notamment a cause des tests de caracteres ... en tout cas il marche chez moi^^)
(ps: je l'utilise pour bannir des ip dans un serveur...enfin bref)
D'avance merci et bonne prog'



FILE* f= fopen("blacklist.cfg","rt");
if (f){
  char c; char* s; unsigned int n;
  do{
    s =NULL; n= 0;
    do {
      c =gets(f);
      if (c!= '\0' && c!='\n' && c!='\t' && c!=EOF){
        s=(char*)realloc(s,n+1);
        if (s) s[n++] =c;
      }
    }while (
c!= '\0' && c!='\n' && c!='\t' && c!=EOF
);
   
s=(char*)realloc(s,n+1);

    if (s) s[n++] ='\0';
    /*** ici "s" a correspond a la ligne ***/
    free(s);
  }while(c:=EOF); //on fait ca pour toutes les lignes du fichier
  fclose(f);

}



-jl'coWboY-

12 réponses

SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
24 mai 2008 à 16:42
""Par contre je vais devoir trouvé une technique pour pouvoir lire un fichier de taille illimitée..."

Lecture par bloc (fread, fseek).
Pour tester si on arrive à la fin du buffer, on peut, par exemple, placer comme dernier caractère, un 0 de fin de chaine.
Disons que chaque adresse est séparée l'une de l'autre par un saut de ligne, si on tombe sur le 0 de fin de chaine avant le \n (d'après le topic tu es sous Linux), on relit le fichier à partir du dernier \n trouvé (dépend de la méthode que tu souhaites employer) pour ainsi replacer au début du buffer (et donc traiter) l'adresse qui a été tronquée.

"je vais devoir tenter d'optimiser la taille de mon buffer, ni trop grande ni trop petite."

Ne te gène pas : Lis par bloc de plusieurs ko voir mo.

"Pour la taille du buffer, suffit de créer un tableau de char pouvant contenir la plus grande valeur possible sur une ligne."

Ici, je voulais parler de la taille du buffer si tu utilisais fgets.
Autrement, étant donnée que les lignes de ton fichier ne sont jamais pareilles, la taille du buffer ne devrait pas en tenir compte.

C++ (@++)<!--
3
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
23 mai 2008 à 22:20
Je ne vois pas comment ça pourrait fonctionner voir même compiler.

c= gets(f);

gets prend, en paramètre, un pointeur char (char*) et non un FILE*.
De plus, cette fonction retourne un char * (le même que celui passé en argument sinon, si fin de fichier atteint, un pointeur nul) et non un char.
Finalement, cette fonction sert à lire dans la console (stdin), pas dans un fichier.

while (c: =EOF);
??? := ???

C++ (@++)<!--
0
NairodDorian Messages postés 130 Date d'inscription lundi 26 juin 2006 Statut Membre Dernière intervention 18 août 2008
23 mai 2008 à 22:21
Bonsoir,

Tu fais beaucoup de realloc ce qui n'est pas négligeable pour le temps d'exécution.
"je l'utilise pour bannir des ip dans un serveur"

Les adresses ip ont la forme : xxx.xxx.xxx.xxx

donc s[4 * 4 + 1] ce qui évite les realloc
Partant de là tu peux optimisé ton code.
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
23 mai 2008 à 22:28
"(le même que celui passé en argument sinon, si fin de fichier atteint, un pointeur nul)"

Oops. Ce n'est pas la "si fin de fichier atteint" mais plutôt "si fin de flux (stdin) atteint".

C++ (@++)<!--
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Neo_Fr Messages postés 653 Date d'inscription mardi 6 décembre 2005 Statut Membre Dernière intervention 10 novembre 2014 2
23 mai 2008 à 22:37
Un exemple avec ReadLine a dl ici:
http://www.cppfrance.com/codes/WIN32-LIRE-FICHIER-LIGNE-LIGNE_44453.aspx

char szFile[] = "blacklist.cfg";
int i;
LPOPENL lpoLine;
char szIP[32];
lpoLine = OpenLine(szFile, GetTypeOfFile(szFile));
for(i=0; i!=10; i++)
{
ReadLine(lpoLine, i, szIP);
printf("Ligne %i : %s", i, szIP);
}
CloseLine(lpoLine);

Neo_Fr
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
23 mai 2008 à 22:50
Lire par bloc (plusieurs ko) voir tout le fichier d'un coup. Étant donné que les lignes dans le fichier doivent probablement avoir toutes la même taille (16 si on inclut le \n 17 si fichier Windows \r\n), ça ne sera pas bien dur de traiter correctement le buffer et, surtout, ce sera bien plus rapide.

C++ (@++)<!--
0
Utilisateur anonyme
24 mai 2008 à 00:56
oula en effet j'ai pas fait un copié collé mais je l'ai retapé donc ya plein
d'erreur comme l'affectation pour le teste qui est bien sur un "!="..
:s

pour ce qui est de la taille des ip dans mon fichier il se trouve que
non elle non pas toute la meme taille. (ip v4, ip v6 avec des mixes aussi pour
des ports... donc taille variables) donc la taille du buffer reste indeterminée :/

et pour le gets(f) c bien sur un getc(f) :s...

en fait ca marche c pas ca le principe ... j'aurais juste aimé savoir si mon algo en soit pouvait etre amélioré ou pas..
(si vraiment vous voulez je peux placer la source "corrigé" (copié/collé) ).

Merci en tout cas a vous pour vos critiques, j'aurais fait les memes ^^
-jl'coWboY-
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
24 mai 2008 à 03:28
Bien sur qu'il peut être amélioré.
Lire caractère par caractère puis faire un realloc à chaque caractère est tout simplement catastrophique pour les performances.

Comme je disais, tu peux lire tout d'un coup si le fichier n'est pas trop gros puis faire les traitements sur le buffer. Tu peux aussi lire par bloc.

Si tu souhaite cependant rester avec une lecture ligne par ligne (que je déconseille fortement pour des projets plus ambitieux), tu peux utiliser fgets.
Pour la taille du buffer, suffit de créer un tableau de char pouvant contenir la plus grande valeur possible sur une ligne.

C++ (@++)<!--
0
Utilisateur anonyme
24 mai 2008 à 14:02
1h oui pas bête du tout, moi je m'obstinais à parser mon fichier..je vais parser mon buffer alors.
Par contre je vais devoir trouvé une technique pour pouvoir lire un fichier de taille illimitée...
Merci bien je vois comment faire! (enfin je crois ^^)
Une derniere question, connaissez vous des noms de programmes qui permettent de calculer l'optimisation d'un programme ? (le temps, le nombre de directives processeurs, la charge du CPU, etc...)
Si je suis ton principe SAKingdom, je vais devoir tenter d'optimiser la taille de mon buffer, ni trop grande ni trop petite.

Merci bien en tout cas a vous ;)
-jl'coWboY-
0
Utilisateur anonyme
24 mai 2008 à 17:40
héhé réponse accéptée :)
Par contre, si je me rappel bien le fseek n'est -il pas tres couteux ? bref en tout cas merci bien je vais faire qqch comme ca ;) ca va alléger mon serveur je pense et le fluidifier mes threads :)
-jl'coWboY-
0
SAKingdom Messages postés 3212 Date d'inscription lundi 7 novembre 2005 Statut Membre Dernière intervention 16 février 2009 15
24 mai 2008 à 17:48
Je ne sais pas trop. fseek ne sert qu'à déplacer le "curseur" de lecture/écriture à une position donnée dans un fichier.

Dans tout les cas, ça ne sera pas plus coûteux qu'une série de fgetc ou fgets.

C++ (@++)<!--
0
Utilisateur anonyme
24 mai 2008 à 18:00
héhé pas faux mais bon c'était mon 1er jet !^^
Et dans le pir des cas je mettrais des bouts de codes en asm et hop l'affair est réglée =)
Merci bien en tout cas a toi et a tout tes conseils ;)
-jl'coWboY-
0
Rejoignez-nous