2010-09-02 15 views
6

Je suis très nouveau dans le monde de la gestion des erreurs C++, mais on m'a dit ici:
Checking for file existence in C++Try-Catch Bloc C++ File-IO erreurs ne fonctionne pas

... que la meilleure façon de contrôles pour l'existence de fichier était avec un bloc try-catch. De mes connaissances limitées sur le sujet, cela semble être un bon conseil. Je trouve ce bout de code:
http://www.java2s.com/Tutorial/Cpp/0240__File-Stream/Readafileintrycatchblock.htm

#include <fstream> 
#include <iostream> 
using namespace std; 

int main() 
{ 
    try{ 
     char buffer[256]; 
     ifstream myfile ("test.txt"); 

     while (! myfile.eof()) 
     { 
     myfile.getline (buffer,100); 
     cout << buffer << endl; 
     } 
    }catch(...){ 
    cout << "There was an error !\n"; 
    } 
    return 0; 
} 

... mais quand je compile en utilisant

g++ -Wall -pedantic -o test_prog main.cc 

et exécuter le programme dans un répertoire où test.txt n'existe pas, la prog continue de cracher des lignes vides vers le terminal. Quelqu'un peut-il comprendre pourquoi?

Est également ce un bon moyen de vérifier l'existence de fichier pour un fichier que vous voulez ouvrir et lire (par rapport à quelque chose où vous indexez un tas de fichiers et les vérifier)?

Merci!

+2

[Votre logique de lecture de fichier est incorrecte.] (Http://punchlet.wordpress.com/2009/12/01/hello-world/) Et utilisez 'std :: string'. Et les flux n'utilisent pas d'exceptions, par défaut. – GManNickG

+0

Ce n'est pas le mien ... J'ai eu le code d'un site tutoriel, comme je l'ai mentionné;) donc si les flux n'utilisent pas d'exceptions, comment devrais-je détecter les erreurs si le fichier n'existe pas ??? –

+0

Ah. Le site craint alors, pas une surprise. Vous devriez obtenir [un livre] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) si vous voulez vraiment apprendre. – GManNickG

Répondre

10

Dans les iostreams C de ne pas jeter exeptions par défaut. Qu'est-ce que vous avez besoin est

ifstream myfile("test.txt"); 

if(myfile) { 
    // We have one 
} 
else { 
    // we dont 
} 
+0

Alors, quel est le meilleur (et pourquoi) - cela ou autoriser les exceptions comme l'illustre clairement? –

+0

@Jason: N'utilisez pas d'exceptions. Testez simplement l'objet de flux de fichiers. –

11

Par défaut, les objets fstream ne sont pas lancés. Vous devez utiliser void exceptions (iostate except); pour définir le comportement d'exception. Vous pouvez récupérer les paramètres actuels en utilisant iostate exceptions () const;. Modifiez votre code un peu:

#include <fstream> 
#include <iostream> 
#include <stdexcept> 
using namespace std; 

int main() 
{ 
    try{ 
     char buffer[256]; 
     ifstream myfile ("test.txt"); 
     myfile.exceptions (ifstream::eofbit | ifstream::failbit | ifstream::badbit); 
     while (file) 
     { 
     myfile.getline (buffer,100); 
     cout << buffer << endl; 
     } 
    }catch(std::exception const& e){ 
    cout << "There was an error: " << e.what() << endl; 
    } 
    return 0; 
} 
8

tout d'abord, pour le bloc try faire du bien, vous devez activer des exceptions pour le flux.

En second lieu, une boucle comme:

while (! myfile.eof()) 

ne mènera à rien que des ennuis, et vous voyez ici. Le problème (dans ce cas) est que lorsque le fichier a échoué à ouvrir, eof ne sera jamais signalé - vous ne pouvez pas/ne pas atteindre la fin du fichier car il est aucun fichier. Par conséquent, votre boucle s'exécute pour toujours, sur une recherche existentialiste pour la fin d'un fichier inexistant. Fixer la boucle, et les choses vont mieux pressé:

char buffer[256]; 
ifstream myfile ("test.txt"); 

while (myfile.getline(buffer,100)) 
{ 
    cout << buffer << endl; 
} 

Pendant que vous y êtes, un peu plus de fixation ne serait pas mal (sauf si vous avez vraiment voulu dire à utiliser moins de la moitié de l'espace que vous alloué pour votre tampon):

char buffer[256]; 
ifstream myfile ("test.txt"); 

while (myfile.getline(buffer,sizeof(buffer))) 
{ 
    cout << buffer << endl; 
} 

Ou, bien sûr, d'éliminer complètement le problème:

std::string buffer; 
ifstream myfile("test.txt"); 
while (getline(myfile, buffer)) 
    cout << buffer << "\n"; 

Edit: notez que aucun de ceux-ci (au moins actuellement) dépend des exceptions du tout. Ils sont tous configurés pour écrire une ligne à la sortie si nous avons réussi à essayer de lire une ligne à partir de l'entrée. Si le fichier ne s'est pas ouvert, le corps de la boucle ne s'exécutera tout simplement pas, car nous ne pourrons pas lire depuis un fichier qui ne s'est pas ouvert.Si nous voulons imprimer un message d'erreur indiquant à l'utilisateur que le fichier ne s'est pas ouvert, nous devons gérer cela séparément de ce qui précède. Par exemple:

ifstream myfile("test.txt"); 

if (!myfile) { 
    std::cerr << "File failed to open"; 
    return FAIL; 
} 

while (std::getline(myfile // ...