IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Nombre de lignes dans un fichier


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 421
    Par défaut Nombre de lignes dans un fichier
    Bonjour à tous,

    J'ai écrit un programme qui compte le nombre de lignes dans un fichier.
    Mon souci c'est que comme mes fichiers contiennent beaucoup de données, le programme met un certain temps.
    J'aimerais savoir s'il existe une méthode plus rapide (toujours en C) pour compter les lignes dans un fichier ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
     
    int LigneFichier(FILE *fichier)
    {
     
     int nrow=0;
      char c;
     
           rewind(fichier);
     
     
       while((c=fgetc(fichier)) != EOF){
     
                                    if(c == '\n') ++nrow;
                                 }
      rewind(fichier);
    return(nrow);
    }

  2. #2
    Membre expérimenté Avatar de ManusDei
    Homme Profil pro
    vilain troll de l'UE
    Inscrit en
    Février 2010
    Messages
    1 624
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : vilain troll de l'UE

    Informations forums :
    Inscription : Février 2010
    Messages : 1 624
    Par défaut
    Tu peux utiliser fgets plutôt que fgetc, par exemple.

    C'est probablement pas optimal, mais ça devrait être déjà meilleur.

  3. #3
    CGi
    CGi est déconnecté
    Expert confirmé
    Avatar de CGi
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 061
    Détails du profil
    Informations personnelles :
    Localisation : France, Allier (Auvergne)

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 061
    Par défaut
    Le charger par blocs avec fread et compter les '\n' dans les blocs.
    ça éviterait les appels aux fonctions fgets ou fgetc.
    Site : http://chgi.developpez.com

    Pourquoi faire simple quand on peut faire compliqué ? (Jacques Rouxel)

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 421
    Par défaut
    Le problème avec fgetc c'est qu'il faut je connaisse le nombre d'éléments dans chaque ligne il me semble.
    Pour fread je n'ai pas trop compris son utilisation dans mon cas.

  5. #5
    CGi
    CGi est déconnecté
    Expert confirmé
    Avatar de CGi
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 061
    Détails du profil
    Informations personnelles :
    Localisation : France, Allier (Auvergne)

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 061
    Par défaut
    fread sert à lire les fichiers binaires, mais un fichier texte est un fichier binaire (l'inverse n'est pas focement vrai).
    Ton problème est un problème de rapidité, c'est pour cela que je t'ai proposé fread. Tu fais des boucles sur les blocs lus pour compter tes '\n'

    Fait les tests avec ces deux codes :

    avec getc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
     
    #include <stdio.h>
     
    int main(void)
    {
        int nrow=0;
        char c;
        FILE* MyFile = NULL;
        MyFile = fopen("fichier.txt", "r");
        if(MyFile)
        {
            while((c=fgetc(MyFile)) != EOF){
                                    if(c == '\n') ++nrow;
                                 }
        printf("%d", nrow);
        fclose(MyFile);
        }
        return 0;
    }
    avec fread :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    #include <stdio.h>
     
    #define BUFSIZE 4096
     
    int main(void)
    {
        int i;
        int clu;
        int nrow=0;
        char buffer[BUFSIZE];
        FILE* MyFile = NULL;
        MyFile = fopen("fichier.txt", "r");
        if(MyFile)
        {
            while(clu = fread(buffer, sizeof(char), BUFSIZE, MyFile))
            {
                for(i=0; i<clu; i++) if(buffer[i]=='\n') nrow++;
            }
        printf("%d", nrow);
        fclose(MyFile);
        }
        return 0;
    }
    Tu verras la différence !
    Site : http://chgi.developpez.com

    Pourquoi faire simple quand on peut faire compliqué ? (Jacques Rouxel)

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 421
    Par défaut
    ah ok!
    Merci!
    j'ai une question et si la taille de mes lignes dépasses la taille du Buffer qu'est ce qui se passe ?

  7. #7
    Membre Expert Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Par défaut
    La version GNU de wc ("wc - print newline, word, and byte counts for each file") utilise aussi cette approche (fread).

    Par contre, pour compter le nombre de '\n', c'est memchr (string.h) qui est utilisé.

    Ici, ça revient à remplacer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while(clu = fread(buffer, sizeof(char), BUFSIZE, MyFile))
    {
        for(i=0; i<clu; i++) if(buffer[i]=='\n') nrow++;
    }
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while (clu = fread(buffer, sizeof(char), BUFSIZE, MyFile))
    {
        char *p = buffer;
        while (p = memchr(p,'\n',(buffer+clu)-p))
        {
            p++;
            nrow++;
        }
    }
    On y gagne encore quelque chose :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    plx@sony:~$ time ./cgi_orig Bureau/POINTS_LIAISONS.TXT 
    4677482
    real	0m1.151s
    user	0m1.016s
    sys	0m0.128s
    plx@sony:~$ 
    plx@sony:~$ time ./cgi_sauce_gnu Bureau/POINTS_LIAISONS.TXT 
    4677482
    real	0m0.237s
    user	0m0.104s
    sys	0m0.132s
    plx@sony:~$ 
    plx@sony:~$ time wc -l Bureau/POINTS_LIAISONS.TXT 
    4677482 Bureau/POINTS_LIAISONS.TXT
     
    real	0m0.245s
    user	0m0.096s
    sys	0m0.144s
    plx@sony:~$

  8. #8
    Membre Expert Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Par défaut
    et si la taille de mes lignes dépasses la taille du Buffer qu'est ce qui se passe ?
    buffer ne contiendra pas toujours un caractère '\n' et, dans ce cas, la boucle de comptage (for (i=0, ... ou while (p = memchr(...) n'incrémentera pas nrow.

    En passant BUFSIZE à 40 (plus petit que les lignes de mon fichier), on obtient le même nombre de lignes, seules les performances s'en ressentent (c'est normal) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    plx@sony:~$ time ./cgi_sauce_gnu Bureau/POINTS_LIAISONS.TXT 
    4677482
    real	0m0.826s
    user	0m0.648s
    sys	0m0.176s
    plx@sony:~$

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 421
    Par défaut

    buffer ne contiendra pas toujours un caractère '\n' et, dans ce cas, la boucle de comptage (for (i=0, ... ou while (p = memchr(...) n'incrémentera pas nrow.

    En passant BUFSIZE à 40 (plus petit que les lignes de mon fichier), on obtient le même nombre de lignes, seules les performances s'en ressentent (c'est normal)

    Je pense qu'il y a un souci si le dernier caractère lu n'est pas une fin de lignes.
    On fait comment pour palier à ce cas ?

  10. #10
    Membre Expert Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Par défaut
    Je pense qu'il y a un souci si le dernier caractère lu n'est pas une fin de lignes.
    Non. Pourquoi ?

    Tu pourrais, de la même manière (en remplaçant '\n' dans le test ou dans memchr), compter le nombre de 'a' de ton fichier par exemple.

    Dans l'algo, le '\n' ne tient pas un rôle particulier. C'est parce que '\n' équivaut à une ligne qu'on s'intéresse à ce caractère. fread lit des octets quelconques. Il ne se cale pas sur tel ou tel caractère (comme fgets).

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    421
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 421
    Par défaut
    J'ai pas compris !
    Dans certain fichier il se peut que le dernier caractère lu n'est pas \n.
    Cela cause un problème car on associe à une ligne un \n.

  12. #12
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 492
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 492
    Billets dans le blog
    1
    Par défaut
    Si ton fichier se termine par \n, alors tu as une ligne vide à la fin de ton fichier... qui ne se termine pas par \n.

  13. #13
    Membre Expert Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Par défaut
    J'ai pas compris !
    Dans certain fichier il se peut que le dernier caractère lu n'est pas \n.
    Cela cause un problème car on associe à une ligne un \n.
    Ok. J'avais compris "dernier caractère lu" par "dernier caractère lu ... lors de l'appel à fread", pas dernier caractère du fichier. Ma réponse (tu peux la reprendre) était faite dans ce contexte.

    Je dirais que ça va dépendre de l'éditeur. Je prends ce que j'ai sous la main, en tapant deux lignes "blabla" mais sans faire de <RETURN> à la fin de la deuxième

    Les extensions correspondent à l'éditeur (Text Wrangler est un éditeur sous MacOSX).

    Sous Linux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    plx@sony:~$ od -c blabla.vi
    0000000   b   l   a   b   l   a  \n   b   l   a   b   l   a  \n
    0000016
    plx@sony:~$ od -c blabla.gedit
    0000000   b   l   a   b   l   a  \n   b   l   a   b   l   a  \n
    0000016
    plx@sony:~$ od -c blabla.eclipse
    0000000   b   l   a   b   l   a  \n   b   l   a   b   l   a
    0000015
    et sous MacOSX :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    pascal@kermit:~$ od -c blabla.text_wrangler
    0000000   b   l   a   b   l   a  \n   b   l   a   b   l   a
    0000015
    pascal@kermit:~$
    Encore une histoire de poteaux et d'intervalles ...

    Ce qui est sur, c'est que dans le code de wc GNU, c'est bien le nombre de caractères '\n' qui est pris en compte. Si tu veux blinder, ajoute 1 si le dernier caractère lu (dernier caractère du fichier !) n'est pas '\n'

  14. #14
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Ce qui pose "problème" ce n'est pas la dernière ligne, c'est la première ligne. Le nombre de lignes d'un ficher c'est le nombre de retours à la ligne, plus 1 (pour la première ligne) si le fichier contient au moins un caractère.

Discussions similaires

  1. nombre de lignes dans un fichier .txt
    Par marieo dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 31/10/2007, 15h22
  2. Compter le nombre de ligne dans un fichier
    Par amine_en_france dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 31/05/2007, 17h19
  3. Nombre de lignes dans un fichier
    Par theshark85 dans le forum C
    Réponses: 48
    Dernier message: 05/05/2006, 10h15
  4. [Fichier] Nombre de ligne dans un fichier texte
    Par NewSer dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 10/11/2004, 16h58
  5. Réponses: 2
    Dernier message: 02/03/2004, 19h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo