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 :

Entrée sortie fichiers


Sujet :

C

  1. #1
    Inactif
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 136
    Points : 25
    Points
    25
    Par défaut Entrée sortie fichiers
    Bonjour,
    je crois voir comment récupérer la seconde ligne d'un fichier (on utilise fgetc tant qu'on n'a pas \n), mais comment récupérer la dernière, sans lire toutes les précédentes, puisqu'il s'agit d'un flux et qu'on ne peut donc utiliser un "fgetc qui partirait de la fin" ?

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 076
    Points : 2 328
    Points
    2 328
    Par défaut
    A priori, non.

    Il faut lire les lignes avec fgets et sauvegarder l'ancienne ligne lu jusqu'a obtention d'un "EOF". La dernière ligne est donc la ligne sauvegarder.

    Après, il y a peut être moyen de faire quelque chose avec FSEEK.
    Si tu connais le nombre de caractère séparant le début/la fin de ton fichier, avec FSEEK tu pourra te positionner a l'endroit voulu.

  3. #3
    Inactif
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 136
    Points : 25
    Points
    25
    Par défaut
    Laissez-moi alors modifier légèrement ma question : dans un très très long fichier, fp pointe sur le milieu du fichier (une ligne quelconque). Je vois comment accéder à la ligne suivante (avec un fgetc), mais comment accéder à la précédente?

  4. #4
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 076
    Points : 2 328
    Points
    2 328
    Par défaut
    Tu pourrai faire une boucle while.
    Tu recupere un caractere, si celui-ci est different de '\n', alors tu fais FSEEK et tu deplace le curseur de deux cran vers l'arriere (caractere lu + nouveau caractere).
    Et tu continue tant que tu n'as pas trouvé deux '\n', le premier etant celui de la ligne ou tu es, le deuxieme etant le '\n' juste avant la ligne que tu souhaite recuperer.

  5. #5
    Inactif
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 136
    Points : 25
    Points
    25
    Par défaut
    Merci beaucoup, je vais réfléchir à votre idée et essayer de l'implémenter. Je reviendrai si j'ai des soucis.

  6. #6
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Un fichier ouvert en mode texte est vu comme un fichier organisé en lignes. Une ligne est une suite de caractères terminée par '\n'. Après avoir ouvert un fichier, il n'y a pas d'autre moyen d'aller à la ligne à part lire les n-1 lignes avant. Il est aussi possible de se positionner à une position sauvegardée par fgetpos à l'aide de la fonction fsetpos. Utiliser ftell/fseek sur un fichier ouvert en mode texte n'est pas portable. Voici un tutoriel pour en savoir plus : Manipulation des fichiers en C.

  7. #7
    Inactif
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 136
    Points : 25
    Points
    25
    Par défaut
    Je vais lire le cours avec attention.
    En fait ce que je cherche à faire est accéder à une date d'un très long log.
    Afin de ne pas lire toutes les lignes (ce qui serait très long), j'avais pensé à faire la recherche de la date par dichotomie, mais pour cela j'ai parfois besoin d'accéder aux caractères précédents un pointeur donné.
    Avez-vous une meilleure idée?

    Au passage, une petite question supplémentaire : pourquoi le nombre de caractères de mon fichier est égal à sa "taille" telle qu'affichée dans ses propriétés ? (sa "taille" ne prend elle pas en compte l'espace requis pour contenir ses propriétés ?)

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Non, elle ne les prend pas en compte. Je ne sais même pas si la partie "taille sur le disque" les compte.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Inactif
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 136
    Points : 25
    Points
    25
    Par défaut
    Ok, merci de la réponse. Et en ce qui concerne l'algorithme le plus efficace pour accéder à une date donnée d'un log, compte tenu des fonctions disponibles en C, qu'est-ce que vous me conseillez?

  10. #10
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Bien entendu, puisque c'est un log, procéder par dichotomie est la meilleure solution. Il faut cependant ouvrir le fichier en mode binaire car fseek ne fait pas bon ménage avec les fichiers ouverts en mode texte. De plus, il faut que chaque ligne contienne un marqueur de début (un # ou un ; par exemple) afin qu'on puisse se positionner facilement en début de la ligne courante après un appel à fseek.

  11. #11
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    J'avais fais une fonction pour extraire une ligne d'un fichier. Si ça peut t'aider là voilà.

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
     
     
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // ExtraireLigne : Extraire la ligne d'un fichier
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Entrée :
    //    + CheminFichier     : char *     -> Le chemin du fichier dont on veut extraire la ligne
    //    + Ligne             : int        -> L'adresse de ligne à extraire
    //    + LigneExraite      : char *     -> La chaine de caractère qui contiendra la ligne à extraire 
    //    + LongueurFiltre    : int  *     -> La longueur de la chaine contenant la ligne à extraire
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    void ExtraireLigne( char *CheminFichier, int Ligne, char **LigneExtraite, int *LongueurLigneExtraite )
    { 
        FILE *Fichier = fopen(CheminFichier,"r");
     
        int   ligne_courante        = 0;
        int   position_caractere    = 0;
        int   position_debut_ligne  = 0;
        int   position_fin_ligne    = 0;
             *LongueurLigneExtraite = 0;
             *LigneExtraite         = NULL;
        char *Test_Realloc          = NULL;
     
        // On parcourt le fichier pour connaitre les positions des caractères du début et de la fin de la ligne à extraire
        char C;
        while( fscanf(Fichier,"%c",&C) != EOF )
             {
                 position_caractere++;
     
                 // On test si le caractère courant est le caractère de changement de ligne
                 if ( C == '\n' )
                    {
                        // On incrémente la valeur de la ligne courante dès qu'on change de ligne
                        ligne_courante++;
     
                        // On sauvegarde alors la position du caractère de la fin de ligne courante
                         position_fin_ligne=position_caractere;
     
                         // On test si la ligne courante est la ligne à extraire
                         if ( ligne_courante == Ligne )
                            {
                                   // On connait les positions du début et de la fin de la ligne, on parcourt à nouveau le fichier
                                   FILE *Fichier=fopen(CheminFichier,"r");
     
                                   int p=0;      
                                   while( fscanf(Fichier,"%c",&C) != EOF )
                                        {
                                            p++;
     
                                            // Si on parcourt les caractères de ligne à extraire, on copie ces caractères
                                            if ( position_debut_ligne <= p && p <= position_fin_ligne )
                                               {
                                                        if( LigneExtraite != NULL && LongueurLigneExtraite != NULL)
                                                          {
                                                                 Test_Realloc=realloc(Test_Realloc, (*LongueurLigneExtraite+1)*sizeof(char));
     
                                                                 if ( Test_Realloc != NULL )
                                                                    {
                                                                          *LigneExtraite                          = Test_Realloc;
                                                                         (*LigneExtraite)[*LongueurLigneExtraite] = C;
                                                                          *LongueurLigneExtraite                  = *LongueurLigneExtraite+1;
                                                                    }
     
                                                               else {
                                                                         *LigneExtraite         = NULL;
                                                                         *LongueurLigneExtraite = 0;
                                                                          printf("\n\nERREUR DANS LA FONCTION ExtraireLigne \n   + ERREUR DANS L'ALLOCATION\n\n");  
                                                                    }             
                                                          }
     
                                                        else printf("\n\nERREUR DANS LA FONCTION ExtraireLigne \n   + VERIFIEZ LE REFECEMENT DE VOS POINTEURS\n\n");
                                               } 
                                        }
     
                                   // On passe à la ligne suivante     
                                   position_debut_ligne=position_fin_ligne+1;
     
                                   fclose(Fichier);
                            }   
     
                         if ( ligne_courante != Ligne )
                            {
                                   // On passe à la ligne suivante 
                                   position_debut_ligne=position_fin_ligne+1;  
     
                            } 
                     }                    
            }  
     
          fclose(Fichier);                   
    }
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Sauf que "r+w" n'est pas un mode d'ouverture valide...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  13. #13
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    Ah... bon juste "r" alors . Encore une de mes inventions... Quel serait alors la bonne syntaxe pour spécifier correctement les droits rwx ?
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Tu ne peux pas en C standard: Tu dois utiliser les fonctions POSIX pour ça (et ne pas être sous Windows).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    Donc en gros on a le droit qu'à un seul droit à l'ouverture : soit lire soit écrire soit exécuter mais aucune combinaison.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  16. #16
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    On ne parle pas de la même chose:

    En droit d'ouverture, tu as lecture seule, écriture seule, lecture/écriture, et les options de création/troncature. C'est standard.

    Mais tu ne contrôles pas les droits qu'aura le fichier sur le disque si tu le crées (même si c'est souvent 0644, soit "rw-r--r--"). Si tu utilises les fonctions POSIX, tu peux spécifier ces droits en plus.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Membre confirmé
    Homme Profil pro
    amateur
    Inscrit en
    Octobre 2007
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : amateur

    Informations forums :
    Inscription : Octobre 2007
    Messages : 731
    Points : 460
    Points
    460
    Par défaut
    D'accord, merci pour la précision.
    UNE REPONSE UTILE : &|| UN PROBLEME RESOLU :

  18. #18
    Inactif
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 136
    Points : 25
    Points
    25
    Par défaut
    Revenons à l'écriture de int goto_prevline(fp) qui permet de placer le pointeur sur la ligne précédente. Je m'embrouille dans les cas particuliers, j'ai des tas de ifs imbriqués. Pouvez-vous m'aider ?

  19. #19
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Si tu veux que ça marche en C standard, je dirais que tu dois mémoriser une liste d'offsets retournés par ftell() (ou potentiellement, seulement un buffer circulaire des X derniers offsets). Et pour revenir au début d'une de ces lignes, utiliser ces offsets avec fseek() et SEEK_SET.

    Dans un fichier texte, le comportement est indéfini par le standard si tu utilises fseek() avec SEEK_CUR, interdisant les déplacements relatifs.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  20. #20
    Inactif
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    136
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 136
    Points : 25
    Points
    25
    Par défaut
    Je ne suis pas sûr d'avoir compris la remarque précédente. Quoiqu'il en soit, j'avais déjà bien entamé l'écriture de l'algorithme proposé précédemment.
    Dites moi ce que vous en pensez :
    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
    int goto_prevline(FILE *fp)
    {
            int c;
            int acc=0;
            if (ftell(fp)==0)
                    return 1;
            else
            {   
                    fseek(fp,1,SEEK_CUR);
                    do  
                    {   
                            fseek(fp,-2,SEEK_CUR);
                            c=fgetc(fp);
                            if (c=='\n')
                                    acc++;
                    }   
                    while ( acc != 2 && (ftell(fp)-2>=0) );
                    if( acc==2 || (acc==1 && ftell(fp)==0) )
                            return 0;
                    else
                            return 1;
            }   
    }

Discussions similaires

  1. Réponses: 0
    Dernier message: 24/04/2012, 21h30
  2. Réponses: 15
    Dernier message: 01/11/2008, 15h57
  3. Entrée / sortie dans un fichier binaire
    Par mejrs dans le forum Débuter
    Réponses: 1
    Dernier message: 24/05/2008, 16h48
  4. Réponses: 17
    Dernier message: 07/05/2008, 10h16
  5. Réponses: 11
    Dernier message: 13/10/2004, 00h58

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