Eines der alten Anti-Patterns ist, dass Leute den Fehlerstatus überprüfen und dann ziemlich nutzlose Nachrichten wie "Operation failed" anstatt "Operation Failed weil ..." zurückgeben. Ich möchte, dass C++ - Datei-E/A-Operationen mit Ausnahme fehlschlagen und die Fehlermeldung erhalten, warum sie fehlgeschlagen ist. Insbesondere möchte ich, dass das Objekt stream eine Exception auslöst, wenn die Dateierstellung fehlschlägt, und eine etwas nützlichere Nachricht wie "Berechtigung verweigert" oder "Keine Datei oder Pfad" erhalten.Wie bekomme ich IO-Fehlermeldungen beim Erstellen einer Datei in C++?
Dies ist trivial in Sprachen wie C# oder Java oder Python, aber irgendwie gibt es keine gut dokumentierte Möglichkeit, dies zu tun C++. Standardmäßig schlagen Iostream-Objekte nur unbemerkt fehl. Es gibt einige globale Fehlercodes, aber ich hätte lieber Ausnahmen. Nach viel Sucherei, las ich, dass Sie Ausnahmen mit folgenden Codezeile aktivieren:
my_file.exceptions(flog.exceptions() | std::ios::failbit | std::ifstream::badbit);
Das funktioniert aber jetzt ist die Ausnahme, die ausgelöst wird ist std::ios_base::failure
und die ex.what() gibt nutzlos Zeichenketten wie „basic_ios: :klar". Gemäß der C++ 11 Spezifikationen std::ios_base::failure
sollte von System_error vererbt werden, der .code(). Message() hat, die die Ausnahmebedingungsnachricht geben wird. Lassen Sie uns diese Seltsamkeit hier beiseite und nicht Finger zeigen auf Person, die entschieden, was() sollte nicht tatsächliche Fehlermeldung zurückgeben :). Das Problem ist, dass selbst beim Kompilieren mit C++ 11 und G ++ 4.8.4, ich finde, dass std::ios_base::failure
nicht tatsächlich von system_error geerbt wird.
Fragen
- Warum
std::ios_base::failure
nicht von system_error in neueste G ++ 4.8.4 auch beim Kompilieren mit C++ 11-Modus vererbt wird? Ist die Implementierung von C++ 11 von GCC in diesem Bereich unvollständig oder muss ich etwas mehr tun? - Wie erreiche ich mein Ziel, Ausnahmen auszulösen, wenn IO-Operationen in C++ fehlschlagen und Fehlermeldungen angezeigt werden? Gibt es keine Möglichkeit, dies auch in den neuesten C++ 11 oder C++ 14 zu tun? Was sind die Alternativen?
Hier ist der Beispielcode. Sie können compile and run it here.
#include <iostream>
#include <fstream>
#include <system_error>
int main() {
try {
std::ofstream flog;
flog.exceptions(flog.exceptions() | std::ios::failbit | std::ifstream::badbit);
flog.open("~/watever/xyz.tsv", std::ios::trunc);
}
catch (const std::ios_base::failure &ex) {
std::cout << "ios_base::failure: " << ex.what();
}
catch(const std::system_error& ex) {
std::cout << "system_error: " << ex.code().message();
}
}
musste google http://en.cppreference.com/w/cpp/error/system_error zu finden, aber dank – strangeqargo