ifstream creates file if it doesn't exist
Solution 1
You can set the failbit
in the exceptions flag for the ifstream
:
std::ifstream log;
log.exceptions ( std::ifstream::failbit );
try {
log.open ("test.txt");
}
catch (std::ifstream::failure e) {
std::cout << "Exception opening/reading file\n";
}
I've tested, and ifstream
will throw a failure
exception if the file cannot be opened, e.g. file not found, no read permissions. It will open read-only.
Solution 2
Since you are opening an std::ifstream
it is necessary to add std::ios_base::in
(or any other spelling of the std::ios_base::openmode
) according to 27.9.1.9 [ifstream.members] paragraph 4: The flag is automatically added by the call to open()
. Note that an std::ofstream
or an std::fstream
would automatically add std::ios_base::out
(27.9.1.13 [ofstream.members] paragrpah 3) or std::ios_base::in | std::ios_base::out
(27.9.1.17 [fstream.members] paragraph 3), both of which resulting in a new file being created if it doesn't exist (and there are write permissions, etc.).
If the code you posted creates a new file, the implementation of the standard C++ library is wrong: when only the flag std::ios_base::in
is specified, the file is open "as if" using the open mode "r"
with fopen()
(27.9.1.4 [filebuf.members] paragraph 5). fopen()
in turn doesn't create a new file when it gets an open mode of "r"
(7.21.5.3 paragraph 3).
Jean-Marie Comets
By day: I write hardcore C++ code to handle market data. By night: I try my best to work on as many Rust projects I can. Currently I'm trying to lend a hand with petgraph.
Updated on June 04, 2022Comments
-
Jean-Marie Comets almost 2 years
I'm having some trouble writing a Linux console app which reads apache logs.
I need to handle bash script arguments, the last one being a path to the log file. My problem is that if the file doesn't exist, I would like to throw an exception.
But when I try to open the file in read-only mode, instead of failing it creates the file !
Here's the code :
// logreader.h #include <string> #include <sstream> #include <iostream> #include <fstream> #include <stdexcept> class LogReader { public: LogReader(int, const char **); virtual ~LogReader(); // ... private: std::ifstream log_; }; // logreader.cpp #include <logreader.h> LogReader::LogReader(int argc, const char ** argv): log_() { log_.exceptions(std::ifstream::failbit | std::ifstream::badbit); for (int i = 1; i < argc; ++i) { std::string arg(argv[i]); if (i == argc - 1) { try { log_.open(arg.c_str(), std::ifstream::in); } catch (std::ifstream::failure) { throw std::runtime_error("The file " + arg + " wasn't opened"); } } } } LogReader::~LogReader() { } // main.cpp #include <logreader.h> int main(int argc, const char ** argv) { LogReader(argc, argv); return 0; }
Script call:
jmcomets $ ./test -g -l jmcomets $ ls -l -rw-rw-r-- 1 jmcomets jmcomets 0 Nov 14 22:41 -l