121
ifstream f;
f.open(fileName);

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

エラーメッセージを文字列として取得するには?

4

5 に答える 5

90

失敗したすべてのシステム コールがerrno値を更新します。

ifstreamしたがって、次のようなものを使用して、オープンが失敗したときに何が起こるかについてより多くの情報を得ることができます:

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

ただし、すべてのシステム コールがグローバルerrno値を更新するため、別のシステム コールが の実行f.openと の使用の間にエラーをトリガーすると、マルチスレッド アプリケーションで問題が発生する可能性がありますerrno

POSIX 標準のシステム:

errno はスレッドローカルです。あるスレッドで設定しても、他のスレッドの値には影響しません。


編集(コメントのArne Mertzと他の人々に感謝):

e.what()最初は、これを実装するより C++ の慣用的に正しい方法のように見えましたが、この関数によって返される文字列は実装に依存し、(少なくとも G++ の libstdc++ では) この文字列にはエラーの背後にある理由に関する有用な情報がありません...

于 2013-06-27T09:02:15.830 に答える
34

失敗時にストリームに例外をスローさせることができます。

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 set」が表示され、strerror(errno)「No such file or directory」が表示されました。
  • Ubuntu 13.04、gcc 4.7.3 では、例外に「basic_ios::clear」と表示されます ( 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";
}
于 2013-06-27T08:19:49.277 に答える
25

@Arne Mertz の回答に続いて、C++11以降は( http://www.cplusplus.com/reference/ios/ios_base/failure/std::ios_base::failureを参照)を継承します。これには、返されるエラー コードとメッセージの両方が含まれています。system_errorstrerror(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

于 2016-04-14T04:35:51.277 に答える
12

std::system_error以下のテスト コードに示すように、a をスローすることもできます。このメソッドは、より読みやすい出力を生成するようですf.exception(...)

#include <exception> // <-- requires this
#include <fstream>
#include <iostream>

void process(const std::string& fileName) {
    std::ifstream f;
    f.open(fileName);

    // after open, check f and throw std::system_error with the errno
    if (!f)
        throw std::system_error(errno, std::system_category(), "failed to open "+fileName);

    std::clog << "opened " << fileName << std::endl;
}

int main(int argc, char* argv[]) {
    try {
        process(argv[1]);
    } catch (const std::system_error& e) {
        std::clog << e.what() << " (" << e.code() << ")" << std::endl;
    }
    return 0;
}

出力例 (Ubuntu w/clang):

$ ./test /root/.profile
failed to open /root/.profile: Permission denied (system:13)
$ ./test missing.txt
failed to open missing.txt: No such file or directory (system:2)
$ ./test ./test
opened ./test
$ ./test $(printf '%0999x')
failed to open 000...000: File name too long (system:36)
于 2018-06-30T22:27:07.363 に答える