2013-06-27 49 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 
} 

如何獲得錯誤信息爲字符串?如何獲得錯誤信息時ifstream的打開失敗

+2

[C++ ifstream錯誤檢查]的可能的重複(http://stackoverflow.com/questions/13446593/c-ifstream-error-checking) –

+1

可能的重複[你可以得到一個特定的錯誤條件,當C++流打開失敗?](http://stackoverflow.com/questions/303966/can-you-get-a-specific-error-condition-when-ac-stream-open-fails) – arne

+3

@亞歷法伯:當然。 'cerr <<「錯誤代碼:」<< strerror(errno); //獲取一些與原因相關的信息似乎與問題相關。 –

回答

42

每個系統調用失敗更新errno值。

因此,你可以有什麼發生的更多信息時,ifstream開放使用類似失敗:

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

然而,由於系統調用更新全局errno值,可以在多線程應用程序的問題,如果其他系統調用觸發f.open的執行和使用errno之間的誤差。

在符合POSIX標準的系統:

錯誤號是本地線程;在一個線程設置不影響任何其他線程的 價值。


編輯(感謝阿恩·默茨和評論其他人):

e.what()起初看起來是一個比較C++ - 實現這個的慣用正確的方法,但返回的字符串通過這個函數是依賴於實現的(至少在G ++的libstdC++中),這個字符串沒有關於錯誤原因的有用信息......

+1

'e what()'似乎沒有提供太多的信息,請參閱我的答案的更新。 –

+11

'errno'在現代操作系統上使用線程本地存儲。但是,不能保證'fstream'函數在errno發生後不會破壞'errno'。底層函數可能根本不會設置「errno」(在Linux或Win32上直接調用系統)。這在許多現實世界的實現中不起作用。 – strcat

+0

在MSVC中,'e.what()'總是打印相同的消息''iostream流錯誤'「 – rustyx

21

你可以嘗試讓流拋出失敗異常:

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(),然而,這似乎不是非常有幫助:

  • 我試了一下Win7上,Embarcadero公司的RAD Studio 2010它賦予「​​的ios_base :: failbit集」,而strerror(errno)給出「沒有這樣的文件或目錄。」
  • 在Ubuntu 13.04,GCC 4.7.3異常說「basic_ios ::清晰」(感謝arne

如果e.what()不適合你(我不知道它會告訴你該錯誤,因爲這是不規範),請嘗試使用std::make_error_condition(僅限於C++ 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

謝謝。我沒有測試這個,因爲在註釋中發佈了strerror(errno)',並且使用起來非常簡單。我認爲'e.what'將起作用,因爲'errno'起作用。 –

+0

然後在Matthieus中看到有關多線程的註釋答案 - 我的猜測是'e.what()'將會是'strerror'以線程安全方式返回的結果。兩者都可能依賴於平臺。 –

+0

@AlexFarber:我認爲Arne的答案比我的好。我的解決方案不是解決你的問題的方法。但是,我沒有找到有關C++庫如何將系統調用錯誤映射到'exception.what()'的官方信息。可能是潛入libstdC++源代碼的好機會:-) –

13

以下是關於@Arne Mertz的答案,截至C++ 11 std::ios_base::failuresystem_error繼承(見http://www.cplusplus.com/reference/ios/ios_base/failure/),其中包含兩個錯誤代碼和消息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; 
} 

這將打印No such file or directory.如果fileName不存在。

+5

對於我在MSVC 2015中只打印'iostream流錯誤'。 – rustyx

+0

對我來說,GCC 6.3還會打印'iostream錯誤'。你測試了什麼編譯器?任何編譯器實際上是否提供用戶可讀的失敗原因? – Ruslan

相關問題