39

I am implementing file saving functionality within a Qt application using C++.

I am looking for a way to check to see if the selected file already exists before writing to it, so that I can prompt a warning to the user.

I am using an std::ofstream and I am not looking for a Boost solution.

3

7 Answers 7

72

File Exists Function

Below is one of my favorite tuck-away functions I keep on hand for multiple uses:

 #include <sys/stat.h> /** * File Exist Function * * @desc Check if a file exists * * @param filename - the name of the file to check * * @return 'true' if it exist, otherwise returns false. * */ bool fileExists(const std::string& filename){ struct stat buf; if (stat(filename.c_str(), &buf) != -1){ return true; } return false; } 

I find this solution to be much more tasteful than trying to open a file when you don't intend to stream in or out of it.


Sign up to request clarification or add additional context in comments.

7 Comments

+1 for an example using stat instead of opening a file just to close it.
+1 but return stat(filename.c_str(), &buf) != 1; is rather more compact.
I timed these on a 2.67GHz Intel Xeon. The stat method above took 0.93 microseconds to confirm that a 500MB file existed. The ifstream methods below took 17.4 microseconds on the same file. To tell that no file exists, stat took 0.72 microseconds, ifstream took 2.4 microseconds.
@Steve: Apart from the fact that Matt Phillips' code didn't declare the struct (I assume he meant it to be implied), and the fact that he used != 1 rather than != -1, why wouldn't it have the same effect?
Is there a reason for the use of the struct keyword? It's not necessary in C++, unless there is some name conflict inside the C header that I'm not aware of?
|
43

I suggest ifstream::good()

Here is an example of what using the fstream member function looks like:

 bool fileExists(const char *fileName) { ifstream inFile(fileName); return inFile.good(); } 

The method is short and portable. When the code base is simple this is a good solution to use (no pun intended).

2 Comments

Explanation: Uses the ifstream constructor to attempt to open the file for reading. When the function returns and the ifstream goes out of scope its destructor will implicitly close the file (in the event that the file existed and the open succeeded).
Except that it does the wrong thing: it checks if a file can be opened, not if it exists. If access permissions disallow the user to access it, this function will erroneously claim that the file does not exist, because it will be unable to open it for reading.
11
fstream file; file.open("my_file.txt", ios_base::out | ios_base::in); // will not create file if (file.is_open()) { cout << "Warning, file already exists, proceed?"; if (no) { file.close(); // throw something } } else { file.clear(); file.open("my_file.txt", ios_base::out); // will create if necessary } // do stuff with file 

Note that in case of an existing file, this will open it in random-access mode. If you prefer, you can close it and reopen it in append mode or truncate mode.

4 Comments

Think on what would happen if the file exists, but the user doesn't have access permissions to read it.
@SasQ: Yeah... this is definitely a hack / workaround. The proper solution in C++17 is std::filesystem::exists(), or barring that, stat().
@HighCommander4 “ barring that, stat()”? What's that? What do you intend to tell us?
@John If your standard library implementation does not support std::filesystem yet, you can use the stat() function from the POSIX API (also supported on Windows)
6

With std::filesystem::exists of C++17:

#include <filesystem> // C++17 #include <iostream> namespace fs = std::filesystem; int main() { fs::path filePath("path/to/my/file.ext"); std::error_code ec; // For using the noexcept overload. if (!fs::exists(filePath, ec) && !ec) { // Save to file, e.g. with std::ofstream file(filePath); } else { if (ec) { std::cerr << ec.message(); // Replace with your error handling. } else { std::cout << "File " << filePath << " does already exist."; // Handle overwrite case. } } } 

See also std::error_code.

In case you want to check if the path you are writing to is actually a regular file, use std::filesystem::is_regular_file.

Comments

5

Try ::stat() (declared in <sys/stat.h>)

Comments

2

One of the way would be to do stat() and check on errno.
A sample code would look look this:

#include <sys/stat.h> using namespace std; // some lines of code... int fileExist(const string &filePath) { struct stat statBuff; if (stat(filePath.c_str(), &statBuff) < 0) { if (errno == ENOENT) return -ENOENT; } else // do stuff with file } 

This works irrespective of the stream. If you still prefer to check using ofstream just check using is_open().
Example:

ofstream fp.open("<path-to-file>", ofstream::out); if (!fp.is_open()) return false; else // do stuff with file 

Hope this helps. Thanks!

Comments

0

You can always do

ifstream infile(yourfilename);
if(!infile) //file doesn't exist)
ofstream outfile(yourfilename, ios::app);

Modern C++ (C++ 17 and higher)

#include <filesystem>
if(std::filesystem::exists(yourfilename))
{
//do something

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.