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 :

tester l'existence d'un fichier et plus


Sujet :

C++

  1. #1
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 34
    Points : 21
    Points
    21
    Par défaut tester l'existence d'un fichier et plus
    Bonjour,
    je suis en train d'apprendre à utiliser les strings et les flux en c++ et tout ne fonctionne pas comme je voudrais. Voici mon code
    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
    #include <iostream>
    #include <fstream>
    #include <string>
     
    using namespace std;
     
    char text[100];
     
    bool is_readable(const string &file) //indique si un fichier est lisible (et donc si il existe)
    {
      ifstream fichier(file.c_str());
      return !fichier.fail();
    }
     
    void main()
    {
      string answer;
      string output_file("fichier.dat" );
      ofstream output(output_file.c_str());
     
    if(is_readable(output_file.c_str()))
    {
     cout << output_file << " exists. Do you want to erase this file (type \"erase\" ) or to create a new one (type \"create\" )?" << endl;
     cin >> answer;
     while (strcmp(answer.c_str(),"erase" )==1 || strcmp(answer.c_str(),"create" )==1) //strcmp renvoie 1 quand les chaines sont différentes
     {
       cout << "Choice is incorrect, type \"erase\" or \"create\"." << endl;
       cout << answer << endl;
       cin >> answer;
     }
     if(strcmp(answer.c_str(),"erase" )==0)
     {
        ofstream output(output_file.c_str());
     }
     if(strcmp(answer.c_str(),"create" )==0)
     {
      cout << "Type the new file name" << endl;
      cin >> output_file;
      output.close();
      ofstream output(output_file.c_str());
     }
    }
    }//fin de main
    En gros, je voudrais tester si le fichier "fichier.dat" existe déjà et si c'est le cas permettre à l'utilisateur de l'écraser ou de proposer un nouveau nom. Qu'est ce que je fais mal ?

  2. #2
    Membre éprouvé
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Points : 1 220
    Points
    1 220
    Par défaut
    Bonjour

    Étant donné que tu ne nous donne pas les erreurs que tu rencontre, c'est assez difficile d'évaluer quels sont les problemes, mais déjà, ne crois-tu pas qu'un serait plus sécurisé à la fin de is readable ? si tu ouvre un fichier et que tu ne le ferme pas , le résultat risque de ne pas être bon ...

    bonne chance
    Méphistophélès
    Si la solution ne résout pas votre problème, changez le problème...
    Cours et tutoriels C++ - FAQ C++ - Forum C++.

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut, et bienvenue sur le forum.

    Déjà, je ne vois pas vraiment ce que vient faire ta variable globale
    dans l'histoire...

    Elle n'est absolument pas utile, du moins dans le code que tu nous présente

    Ensuite, tu passe ton temps à convertir des std::string en chaines de caractères "C style" (c_str() renvoie un pointeur sur une... chaine C style) pour, bien souvent, recréer une... std::string...

    Cela a quelque chose de masochiste, non :
    1. La classe std::string est parfaitement copiable et assignable, si le besoin s'en fait sentir
    2. la classe std::string dispose de son propre opérateur de comparaison ==, ce qui permet de ne pas devoir utiliser strcmp
    3. le fait de passer une chaine de caractères C style en paramètre à une fonction qui attend une std::string provoque la création d'une variable temporaire anonyme, ce qui revient à provoquer la copie de la chaine d'origine, alors que, justement, le but recherché par le passage d'une référence (constante ou non) sur une std::string est... d'en éviter la copie
    Contente toi de manipuler tes std::string sans en demander la transformation en chaine "C style" (la classe dispose de tout ce dont tu pourrais avoir besoin, et même plus), et ne demande cette transformation que... quand tu n'as pas le choix (par exemple, lorsqu'elle doit servir comme nom de fichier, ou lorsque tu dois la transmettre à une fonction C).

    Cette première partie de ma réponse ne fait pas vraiment avancer le shmilblick, mais elle te sera surement utile tout au long de ta vie de développeur C++

    Pour quand même t'aider à résoudre ton problème, je vais essayer de décomposer la logique que tu suis:
    1- ofstream output(output_file.c_str()); ouvre le fichier (fichier.dat) en écriture, ce qui a sans doute comme résultat le fait que le système d'exploitation le verrouille dans cet état, afin d'éviter que d'autres applications ne tentent d'y accéder de manière indue.

    2- Alors que fichier.dat est verrouillé en écriture, tu invoque is_readable() en lui passant... le nom du fichier déjà verrouillé par le système.

    3- Tu essaye, dans is_readable(), d'ouvrir un fichier (qui est encore verrouillé par le système) en... lecture.

    4- tu renvoie le résultat de cette tentative d'ouverture.

    Tu t'étonnes que la tentative d'ouverture échoue à chaque fois

    De prime abord, je dirais que c'est parfaitement logique, non

    Ton code devrait donc être modifié pour faire en sorte que... le fichier ne soit en tout état de cause pas ouvert par ton application avant de voir s'il est possible de le lire
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par méphistopheles Voir le message
    <snip> serait plus sécurisé à la fin de is readable ?
    Absolument pas...

    Le destructeur de toute variable créée de manière statique (comprend: sans avoir recours à l'allocation dynamique) est automatiquement appelé lorsque l'on quitte la portée (comprend: le couple d'accolade)dans laquelle la variable est déclarée.

    Et le destructeur des classes *fstream (ifstream et ofstream, vu que ce sont celles qui nous intéressent ) invoque... la fonction close de manière automatique .

    Les choses sont bien faites, non
    si tu ouvre un fichier et que tu ne le ferme pas , le résultat risque de ne pas être bon ...
    Là dessus, je suis d'accord, mais le problème est surtout que c'est la variable de type ofstream déclarée dans la fonction main qui n'est pas détruite au moment où... on quitte la fonction is_readable, ou plutôt au moment où l'on entre dedans (et donc au moment où l'on essaye d'ouvrir le fichier dans is_readable)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre éprouvé
    Avatar de méphistopheles
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    1 551
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 1 551
    Points : 1 220
    Points
    1 220
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Pour quand même t'aider à résoudre ton problème, je vais essayer de décomposer la logique que tu suis:
    1- ofstream output(output_file.c_str()); ouvre le fichier (fichier.dat) en écriture, ce qui a sans doute comme résultat le fait que le système d'exploitation le verrouille dans cet état, afin d'éviter que d'autres applications ne tentent d'y accéder de manière indue.

    2- Alors que fichier.dat est verrouillé en écriture, tu invoque is_readable() en lui passant... le nom du fichier déjà verrouillé par le système.

    3- Tu essaye, dans is_readable(), d'ouvrir un fichier (qui est encore verrouillé par le système) en... lecture.
    Oups, je n'avais pas vu qu'il le verouillait déjà avant. Par contre, est-ce qu'il un destructeur qui déverouillerait éventuellement le fichier à la destruction de ifstream (je pense en sortant de is_readable) ... ? je n'ai rien trouvé à ce sujet.

    EDIT: Arf grilled. ok koala. compris
    Méphistophélès
    Si la solution ne résout pas votre problème, changez le problème...
    Cours et tutoriels C++ - FAQ C++ - Forum C++.

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par méphistopheles Voir le message
    Oups, je n'avais pas vu qu'il le verouillait déjà avant. Par contre, est-ce qu'il un destructeur qui déverouillerait éventuellement le fichier à la destruction de ifstream (je pense en sortant de is_readable) ... ? je n'ai rien trouvé à ce sujet.
    Les réponses se sont visiblement croisées... regarde mon intervention précédente
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    En fait, ce qui ne fonctionne pas bien c'est qu'avec ce code, je sors de la boucle en tapant "create" ce qui a bien pour action de créer un nouveau fichier qui a le nom que je saisis. Par contre, je ne sors jamais de la boucle en tapant "erase". Je n'arrive donc pas à l'effacer pour réécrire dessus.
    J'ai bien compris votre argument sur le fait que j'ouvre le fichier fichier.dat et que je fasse des tests dessus ensuite n'est pas très bien. Cependant je ne sais pas comment faire pour que le flux output soit connu dans la suite. Par ce qu'avec la méthode actuelle, si à la fin du if(is_readable(output_file.c_str())), je rajoute une ligne de ce style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    output << "Hello" << endl;
    le compilateur me dit que output n'est pas défini.
    Est ce que c'est plus clair ?

  8. #8
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    En tenant compte de vos remarques, j'ai maintenant écrit ceci
    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
    #include <iostream>
    #include <fstream>
    #include <string>
     
    using namespace std;
     
    bool is_readable(const string &file) //indique si un fichier est lisible (et donc si il existe)
    {
      ifstream fichier(file.c_str());
      return !fichier.fail();
    }
     
    void main()
    {
      string answer;
      string output_file("fichier.dat");
      ofstream output;
     
    if(is_readable(output_file.c_str()))
    {
     cout << output_file << " exists. Do you want to erase this file (type \"erase\") or to create a new one (type \"create\")?" << endl;
     cin >> answer;
     while (answer!="erase" && answer!="create")
     {
       cout << "Choice is incorrect, type \"erase\" or \"create\"." << endl;
       cout << answer << endl;
       cin >> answer;
     }
     if(answer=="erase")
     {
        ofstream output(output_file.c_str());
     }
     if(answer=="create")
     {
      cout << "Type the new file name" << endl;
      cin >> output_file;
      ofstream output(output_file.c_str());
     }
    }
    output << "Hello" << endl;
    }//fin de main
    Mon problème c'est que le flux de sortie output ne fonctionne pas. Je m'explique. Si je lui dit d'écraser le fichier fichier.dat alors il va bien l'écraser mais il ne va pas écrire Hello dans ce fichier. fichier.dat sera vide. Idem si je dis de créer un nouveau fichier, alors le fichier sera bien créé mais rien ne sera écrit dedans. Est ce que vous avez une idée sur la manière de corriger cela ?

  9. #9
    Membre à l'essai
    Inscrit en
    Août 2008
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 34
    Points : 21
    Points
    21
    Par défaut
    Bon en fait j'ai trouvé une solution. Il suffit juste d'utiliser "open"
    Voici mon code qui fait ce que je veux
    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
    #include <iostream>
    #include <fstream>
    #include <string>
     
    using namespace std;
     
    bool is_readable(const string &file) //indique si un fichier est lisible (et donc si il existe)
    {
      ifstream fichier(file.c_str());
      return !fichier.fail();
    }
     
    void main()
    {
      string answer;
      string output_file("fichier.dat");
      ofstream output;
     
    if(is_readable(output_file.c_str()))
    {
     cout << output_file << " exists. Do you want to erase this file (type \"erase\") or to create a new one (type \"create\")?" << endl;
     cin >> answer;
     while (answer!="erase" && answer!="create")
     {
       cout << "Choice is incorrect, type \"erase\" or \"create\"." << endl;
       cout << answer << endl;
       cin >> answer;
     }
     if(answer=="erase")
     {
        output.open(output_file.c_str());
     }
     if(answer=="create")
     {
      cout << "Type the new file name" << endl;
      cin >> output_file;
      output.open(output_file.c_str());
     }
    }
    output << "Hello" << endl;
    }//fin de main
    N'hésitez pas à me faire des remarques s'il y a des choses qui pourraient être mieux écrites. Merci pour votre aide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [FTP] Tester l'existence d'un fichier.
    Par antony dans le forum Langage
    Réponses: 2
    Dernier message: 03/03/2006, 18h54
  2. [File]Tester l'existence d'un fichier
    Par florantine dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 23/11/2005, 10h45
  3. tester l existence d un fichier sous turbo pascal
    Par Newllite dans le forum Turbo Pascal
    Réponses: 5
    Dernier message: 25/01/2004, 12h47
  4. Peut on tester l'existence d'un fichier ?
    Par Alamassepointcom dans le forum Flash
    Réponses: 2
    Dernier message: 10/10/2002, 12h10

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