103

I have read the answers for What's the best way to check if a file exists in C? (cross platform), but I'm wondering if there is a better way to do this using standard c++ libs? Preferably without trying to open the file at all.

Both stat and access are pretty much ungoogleable. What should I #include to use these?

Community
  • 1
  • 1
c0m4
  • 4,343
  • 10
  • 35
  • 40

10 Answers10

181

Use boost::filesystem:

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
  std::cout << "Can't find my file!" << std::endl;
}
lnafziger
  • 25,760
  • 8
  • 60
  • 101
Andreas Magnusson
  • 7,321
  • 3
  • 31
  • 36
  • 70
    Seems to be a bit of a hazzle to install a huge third party library to do something that *should* be simple – c0m4 Nov 06 '08 at 09:36
  • 92
    Boost is a library where much of what will eventually be a part of C++ standard library is developed. Many of the people involved with boost are people involved with the C++ standard. So boost isn't just *any* third party library. If you're programming in C++ you *should* have boost installed! – Andreas Magnusson Nov 06 '08 at 09:48
  • I seem to recall that b::fs::exists returns "true" on non-existent files on network shares: "\\machine\share\this_file_doesnt_exist" => true. Last time I checked was on boost 1.33, use caution... – rlerallut Nov 06 '08 at 12:54
  • If your compiler comes with a tr1 implementation, you don't even need to install Boost. It will be in the std::tr1::filesystem – Nemanja Trifunovic Nov 06 '08 at 18:17
  • 1
    Actually ASFAIK it didn't make TR1 but will be added at a later stage. I also didn't find any references to it in the official TR1 draft: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf – Andreas Magnusson Nov 07 '08 at 07:56
  • I think they said at BUILD2013 that a standard-committee working group is working on that and they will include it (most likely boost::fs v2) as a package separate from C++14 but at similar time. – Ela782 Aug 08 '13 at 13:23
  • boost::filesystem::exists checks the existance of absolute path. how to check the existence of relative path.? – Pritesh Acharya Jan 13 '14 at 09:26
  • @PriteshAcharya: `boost::filesystem::exists(boost::filesystem::absolute(relativePath))` – Andreas Magnusson Jan 24 '14 at 12:03
  • unfortunately boost filesystem cannot be used in windows phone :(( – Marcel Tricolici Jun 04 '14 at 15:54
  • I agree, even a lot of parts are moved to - or influenced C++ - IMHO boost is not the solution for everything. I appreciate non-templates when possible. Keep your source safe and simple. – HelloWorld Aug 28 '15 at 15:17
  • @HelloWorld: I fail to see *any* templates in the code above. Is the snippet above not the simplest possible? – Andreas Magnusson Sep 01 '15 at 07:51
  • Good tip, but ended up not using it because boost::filesystem::exists ( path.cpp) requires yet another module or library std::locale::locale(char const*) – Rastikan Dec 08 '15 at 22:49
  • Surprised no one has mentioned this, but this will return 'true' for directories too. `myfile.txt` could be a directory on linux or windows. If you want to require it be a file, you can use `boost::filesystem::is_regular_file()`. – void.pointer Aug 21 '19 at 19:08
42

Be careful of race conditions: if the file disappears between the "exists" check and the time you open it, your program will fail unexpectedly.

It's better to go and open the file, check for failure and if all is good then do something with the file. It's even more important with security-critical code.

Details about security and race conditions: http://www.ibm.com/developerworks/library/l-sprace.html

rlerallut
  • 7,545
  • 5
  • 23
  • 21
30

I am a happy boost user and would certainly use Andreas' solution. But if you didn't have access to the boost libs you can use the stream library:

ifstream file(argv[1]);
if (!file)
{
    // Can't open file
}

It's not quite as nice as boost::filesystem::exists since the file will actually be opened...but then that's usually the next thing you want to do anyway.

MattyT
  • 6,531
  • 2
  • 20
  • 17
  • 15
    But with this code you would also jump into the if clause if you don't have permissions for the file, although it exists. In most cases it won't matter, but still worth mentioning. – scigor Jan 26 '11 at 08:05
  • 1
    Noticed that good() also yields true if the given argument denotes a directory, see http://stackoverflow.com/questions/9591036/ifstream-open-doesnt-set-error-bits-when-argument-is-a-directory – FelixJongleur42 Feb 04 '14 at 11:26
16

If your compiler supports C++17 you don't need boost, you can simply use std::filesystem::exists

#include <iostream> // only for std::cout
#include <filesystem>

if (!std::filesystem::exists("myfile.txt"))
{
    std::cout << "File not found!" << std::endl;
}
AlbertM
  • 1,246
  • 14
  • 25
13

Use stat(), if it is cross-platform enough for your needs. It is not C++ standard though, but POSIX.

On MS Windows there is _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64.

activout.se
  • 6,058
  • 4
  • 27
  • 37
  • 1
    and See http://msdn.microsoft.com/en-us/library/14h5k7ff(VS.71).aspx – activout.se Nov 18 '08 at 10:35
  • 2
    Nice answer +1 for **NOT USING BOOST**, since it's an overkill, however it wasn't trivial to write that from what is provided here, so I just posted an answer. Check it please. – gsamaras Jul 28 '16 at 06:42
9

Another possibility consists in using the good() function in the stream:

#include <fstream>     
bool checkExistence(const char* filename)
{
     ifstream Infield(filename);
     return Infield.good();
}
Samer
  • 1,923
  • 3
  • 34
  • 54
9

How about access?

#include <io.h>

if (_access(filename, 0) == -1)
{
    // File does not exist
}
Rob
  • 76,700
  • 56
  • 158
  • 197
7

I would reconsider trying to find out if a file exists. Instead, you should try to open it (in Standard C or C++) in the same mode you intend to use it. What use is knowing that the file exists if, say, it isn't writable when you need to use it?

fizzer
  • 13,551
  • 9
  • 39
  • 61
  • 1
    What if you're writing a `ls`-like program ? I'm guessing the original poster here doesn't want to open the file, at all. Posix's stat function is supposed to give you informations about the file's permissions though, so it would fix that problem. – Michael Mar 29 '16 at 17:06
3

NO REQUIRED, which would be an overkill.


Use stat() (not cross platform though as mentioned by pavon), like this:

#include <sys/stat.h>
#include <iostream>

// true if file exists
bool fileExists(const std::string& file) {
    struct stat buf;
    return (stat(file.c_str(), &buf) == 0);
}

int main() {
    if(!fileExists("test.txt")) {
        std::cerr << "test.txt doesn't exist, exiting...\n";
        return -1;
    }
    return 0;
}

Output:

C02QT2UBFVH6-lm:~ gsamaras$ ls test.txt
ls: test.txt: No such file or directory
C02QT2UBFVH6-lm:~ gsamaras$ g++ -Wall main.cpp
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
test.txt doesn't exist, exiting...

Another version (and that) can be found here.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • Not the downvoter, but the question asked for a cross-platform solution, and stat doesn't exist on all platforms. – pavon Feb 21 '17 at 17:18
  • 1
    This is a good workaround for Android NDK not yet implementing std::filesystem::exists – Antonio May 17 '23 at 08:08
0

If you are already using the input file stream class (ifstream), you could use its function fail().

Example:

ifstream myFile;

myFile.open("file.txt");

// Check for errors
if (myFile.fail()) {
    cerr << "Error: File could not be found";
    exit(1);
}
Reza Saadati
  • 5,018
  • 4
  • 27
  • 64