Question

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.

Was it helpful?

Solution

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

#include <sys/stat.h>
// Function: fileExists
/**
    Check if a file exists
@param[in] filename - the name of the file to check

@return    true if the file exists, else false

*/
bool fileExists(const std::string& filename)
{
    struct stat buf;
    if (stat(filename.c_str(), &buf) != -1)
    {
        return true;
    }
    return false;
}

I find this much more tasteful than trying to open a file if you have no immediate intentions of using it for I/O.

OTHER TIPS

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

This method is so far the shortest and most portable one. If the usage is not very sophisticated, this is one I would go for. If you also want to prompt a warning, I would do that in the main.

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.

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

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!

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top