std::ofstream, check if file exists before writing

81,108

Solution 1

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.

Solution 2

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.

Solution 3

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.

Solution 4

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.

Solution 5

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

Share:
81,108
heroddaji
Author by

heroddaji

Updated on June 19, 2020

Comments

  • heroddaji
    heroddaji almost 4 years

    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.

  • Chris Smith
    Chris Smith almost 13 years
    +1 for an example using stat instead of opening a file just to close it.
  • Matt Phillips
    Matt Phillips about 11 years
    +1 but return stat(filename.c_str(), &buf) != 1; is rather more compact.
  • Schroeder
    Schroeder about 11 years
    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
    Steve over 10 years
    @MattPhillips: But that doesn't seem to have the desired effect.
  • Gurgadurgen
    Gurgadurgen about 10 years
    @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?
  • grubs
    grubs almost 10 years
    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).
  • Kong Chun Ho
    Kong Chun Ho over 7 years
    I think he meant bool fileExists(const std::string& filename) { struct stat buf; return (stat(filename.c_str(), &buf) != -1); }
  • Lightness Races in Orbit
    Lightness Races in Orbit about 7 years
    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?
  • SasQ
    SasQ over 5 years
    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.
  • SasQ
    SasQ over 5 years
    Think on what would happen if the file exists, but the user doesn't have access permissions to read it.
  • HighCommander4
    HighCommander4 about 5 years
    @SasQ: Yeah... this is definitely a hack / workaround. The proper solution in C++17 is std::filesystem::exists(), or barring that, stat().
  • John
    John over 2 years
    @HighCommander4 “ barring that, stat()”? What's that? What do you intend to tell us?
  • HighCommander4
    HighCommander4 over 2 years
    @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)