2013-06-27 11 views
55
ifstream f; 
f.open(fileName); 

if (f.fail()) 
{ 
    // I need error message here, like "File not found" etc. - 
    // the reason of the failure 
} 

Come ottenere il messaggio di errore come stringa?Come ottenere un messaggio di errore se openstream fallisce

+2

possibile duplicato di [C++ ifstream Error Checking] (http://stackoverflow.com/questions/13446593/c-ifstream-error-checking) –

+1

possibile duplicato di [È possibile ottenere una condizione di errore specifica quando si apre un flusso C++ fallisce?] (http://stackoverflow.com/questions/303966/can-you-get-a-specific-error-condition-when-ac-stream-open-fails) – arne

+3

@Alex Farber: sicuro. 'cerr <<" Codice errore: "<< strerror (errno); // Ottieni informazioni sul motivo per cui sembra pertinente alla domanda. –

risposta

42

Ogni chiamata di sistema che non riesce aggiornare il valore errno.

Quindi, si può avere più informazioni su ciò che accade quando un aperto ifstream fallisce usando qualcosa come:

cerr << "Error: " << strerror(errno); 

Tuttavia, dal momento che ogni chiamata di sistema aggiorna il valore globale errno, è potrebbe avere problemi in un'applicazione multithread, se un'altra chiamata di sistema attiva un errore tra l'esecuzione di f.open e l'uso di errno.

On sistema con standard POSIX:

errno è thread-locale; impostandolo in un thread non influisce sul suo valore in nessun altro thread.


Modifica (grazie a Arne Mertz e altre persone nei commenti):

e.what() sembravano in un primo momento ad essere un altro C++ - idiomaticamente modo corretto di attuazione del presente, ma la stringa restituita questa funzione è dipendente dall'implementazione e (almeno nel libstdC++ di G ++) questa stringa non ha informazioni utili sul motivo dell'errore ...

+1

'e .what() 'non sembra dare molte informazioni, vedere aggiornamenti alla mia risposta. –

+11

'errno' utilizza l'archiviazione locale dei thread sui sistemi operativi moderni. Tuttavia, non vi è alcuna garanzia che le funzioni 'fstream' non clobber' errno' dopo che si è verificato un errore. Le funzioni sottostanti potrebbero non impostare 'errno' affatto (chiamate di sistema dirette su Linux o Win32). Questo non funziona su molte implementazioni del mondo reale. – strcat

+0

In MSVC, 'e.what()' stampa sempre lo stesso messaggio "' errore di streaming iostream' " – rustyx

21

Si potrebbe provare a lasciare che il flusso di un'eccezione in caso di fallimento:

std::ifstream f; 
//prepare f to throw if failbit gets set 
std::ios_base::iostate exceptionMask = f.exceptions() | std::ios::failbit; 
f.exceptions(exceptionMask); 

try { 
    f.open(fileName); 
} 
catch (std::ios_base::failure& e) { 
    std::cerr << e.what() << '\n'; 
} 

e.what(), tuttavia, non sembra essere molto utile:

  • ho provato su Win7, Embarcadero RAD Studio 2010 dove fornisce "ios_base :: failbit set" mentre strerror(errno) restituisce "Nessun file o directory di questo tipo".
  • Su Ubuntu 13.04, 4.7.3 gcc eccezione dice "basic_ios :: Clear" (grazie a arne)

Se e.what() non funziona per voi (io non so quello che vi dirà circa l'errore, dal momento che non è standardizzato), provare a utilizzare std::make_error_condition (C++ solo 11):

catch (std::ios_base::failure& e) { 
    if (e.code() == std::make_error_condition(std::io_errc::stream)) 
    std::cerr << "Stream error!\n"; 
    else 
    std::cerr << "Unknown failure opening file.\n"; 
} 
+0

Grazie. Non ho provato questo perché 'strerror (errno)' pubblicato nei commenti funziona e molto semplice da usare. Penso che 'e.what' funzionerà, dato che' errno' funziona. –

+0

Poi vedi le annotazioni sul multithreading nella risposta di Matthieus - la mia ipotesi è che 'e.what()' sarà ciò che 'strerror' restituisce, in un modo sicuro. Entrambi probabilmente dipenderanno dalla piattaforma. –

+0

@AlexFarber: Penso che la risposta di Arne sia migliore della mia. La mia soluzione non è il _C++ - modo_ di risolvere il tuo problema. Tuttavia, non ho trovato informazioni ufficiali su come la libreria C++ mappasse gli errori di chiamata di sistema su 'exception.what()'. Potrebbe essere una buona occasione per approfondire il codice sorgente di libstdC++ :-) –

13

In seguito alla risposta di @Arne Mertz, come da C++ 11 std::ios_base::failure eredita da system_error (vedere http://www.cplusplus.com/reference/ios/ios_base/failure/), che contiene sia il codice di errore che il messaggio restituito da strerror(errno).

std::ifstream f; 

// Set exceptions to be thrown on failure 
f.exceptions(std::ifstream::failbit | std::ifstream::badbit); 

try { 
    f.open(fileName); 
} catch (std::system_error& e) { 
    std::cerr << e.code().message() << std::endl; 
} 

Questo stampa No such file or directory. se fileName non esiste.

+5

Per me in MSVC 2015 viene stampato solo' errore di streaming iostream'. – rustyx

+0

Per me GCC 6.3 stampa anche 'errore iostream'. Che compilatore hai testato? Qualche compilatore fornisce effettivamente un motivo di errore leggibile dall'utente? – Ruslan