621

I would like to find the fastest way to check if a file exists in standard C++11, 14, 17, or C. I have thousands of files and before doing something on them I need to check if all of them exist. What can I write instead of /* SOMETHING */ in the following function?

inline bool exist(const std::string& name)
{
    /* SOMETHING */
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Vincent
  • 57,703
  • 61
  • 205
  • 388
  • 1
    Not sure how checking for existence plays out on the processor vs drive speeds, but I'll bet it's the drive being slow. – chris Oct 08 '12 at 01:12
  • 2
    `boost::filesystem` seems to use `stat()`. (Assuming from the documentation.) I don't think you can do much faster for FS calls. The way to make what you're doing fast is "avoid looking at thousands of files." – millimoose Oct 08 '12 at 01:15
  • I think this was already answered: [http://stackoverflow.com/questions/4316442/stdofstream-check-if-file-exists-before-writing][1] [1]: http://stackoverflow.com/questions/4316442/stdofstream-check-if-file-exists-before-writing – eLRuLL Oct 08 '12 at 01:16
  • 26
    [TOCTOU](http://en.wikipedia.org/wiki/Time_of_check_to_time_of_use) question: how do you know the file isn't unlinked between your exists() check and your *"doing something on it"*? – pilcrow Oct 08 '12 at 01:16
  • 10
    @pilcrow Good point, but there's a fairly wide range of applications that don't need that much correctness. E.g. `git push` probably doesn't bother to make sure you're not touching the working tree after the initial dirty check. – millimoose Oct 08 '12 at 01:27
  • @Duck `unistd.h` is POSIX, not the pedantically defined libc. Of course, I can't think of a C/C++ implementation that wouldn't have it, or `stat()`, except for some sort of weird embedded environment which doesn't really fit the "thousands of files" requirement. Which makes the "no OS APIs" kind of a dumb restriction, seeing as fiddling with the filesystem is indeed the domain of the OS. – millimoose Oct 08 '12 at 01:29
  • 13
    'I can't think of a C/C++ implementation that wouldn't have it' -- Windows does not provide a POSIX environment. – Jim Balter Oct 08 '12 at 01:58
  • Check out this thread: http://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c-cross-platform – Jack Oct 08 '12 at 03:54
  • @JimBalter: Windows Services For Unix (Interix)? – el.pescado - нет войне Nov 07 '13 at 17:00
  • 1
    @el pescado It's a "subsystem", not Windows itself. – Jim Balter Nov 07 '13 at 18:23
  • 3
    Possible duplicate of [std::ofstream, check if file exists before writing](http://stackoverflow.com/questions/4316442/stdofstream-check-if-file-exists-before-writing) – MD XF Feb 27 '17 at 04:17
  • 3
    Why? 'Doing something on them' such as what? If that involves opening the file, just try to open it and handle the error if it doesn't exist. Adding another check beforehand is just a waste of time and soace, and adds a timing-window problem. – user207421 Feb 16 '19 at 09:04
  • Old wine in new tubes. You find everything on windows you find in unixes - only under different names - and sometimes better and sometimes worse. https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-pathfileexistsa – BitTickler May 18 '23 at 10:05

23 Answers23

1006

Well I threw together a test program that ran each of these methods 100,000 times, half on files that existed and half on files that didn't.

#include <sys/stat.h>
#include <unistd.h>
#include <string>
#include <fstream>

inline bool exists_test0 (const std::string& name) {
    ifstream f(name.c_str());
    return f.good();
}

inline bool exists_test1 (const std::string& name) {
    if (FILE *file = fopen(name.c_str(), "r")) {
        fclose(file);
        return true;
    } else {
        return false;
    }   
}

inline bool exists_test2 (const std::string& name) {
    return ( access( name.c_str(), F_OK ) != -1 );
}

inline bool exists_test3 (const std::string& name) {
  struct stat buffer;   
  return (stat (name.c_str(), &buffer) == 0); 
}

Results for total time to run the 100,000 calls averaged over 5 runs,

Method Time
exists_test0 (ifstream) 0.485s
exists_test1 (FILE fopen) 0.302s
exists_test2 (posix access()) 0.202s
exists_test3 (posix stat()) 0.134s

The stat() function provided the best performance on my system (Linux, compiled with g++), with a standard fopen call being your best bet if you for some reason refuse to use POSIX functions.

IInspectable
  • 46,945
  • 8
  • 85
  • 181
PherricOxide
  • 15,493
  • 3
  • 28
  • 41
  • 51
    None of the methods above check for existence, but rather accessibility. I don't know of a single standard C or C++ way to check for existence, though. – IInspectable Sep 09 '13 at 21:32
  • 15
    `stat()` seems to check for existence. – el.pescado - нет войне Nov 07 '13 at 16:57
  • 24
    I imagine for the ifstream method, you don't need `f.close()` as f goes out of scope at the end of the function. So `return f.good()` could replace the `if` block? – ilent2 Feb 21 '14 at 02:38
  • 1
    Why not use const char * instead od string in exists_test1? Then you can use it also in ANSI C programs. – nosbor Jul 20 '14 at 14:01
  • 14
    You can also use/test http://en.cppreference.com/w/cpp/experimental/fs/exists from upcoming standard – zahir Aug 22 '14 at 14:10
  • Some compilers may fail on `stat()` without `#include `. Remember to include if it fails. – Jet Jun 08 '15 at 18:45
  • 5
    The first one could be just `return ifstream(filename).good();` – Emil Laine Apr 17 '16 at 23:04
  • note that if the path is a directory the result of the fopen/ifstream tests are system-dependent – tamas.kenez May 13 '16 at 14:11
  • was this a fair test tho? in test 0 and test 1 you read the contents of the files, which of course would impede the performance, but in test 3 and i think test 2, you don't - you simply check if file path exists. – Evgeny Danilenko Feb 08 '18 at 00:25
  • 2
    @EvgenyDanilenko Where are the file contents being read? The file is being _opened for reading_, yes, but that's very different from actually reading the contents of the file. – Nic May 14 '18 at 17:54
  • @EvgenyDanilenko 1) Nothing is being read (other than the directory, searching for the named entry ... which all of these do, and must be done). 2) Of course it's a fair test, and it fairly shows that open is slower. "fair" doesn't mean to make slower methods appear to be just as fast as faster methods, and it's not clear how you think it could be made fairer. – Jim Balter Oct 01 '18 at 08:25
  • 2
    i know this is compiler-specific, but now that std::filesystem::exists was added (in C++17) can you please add a std::filesystem::exists benchmark to the list? – hanshenrik Mar 01 '19 at 22:17
  • Ok, i am really confused with this. I've found a bunch of similar answers/comments but no one actually says where that `stat` is ( in which library ) and where to find it in different OS. I am using cygwin so some basic POSIX functionality should be available on windows. Could you include which functionality is derived from which header, and some cross OS equivalents ? All i've found is this *https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions?view=vs-2019*... but honestly i might as well be blind. – Danilo Aug 08 '19 at 11:31
  • @IInspectable "None of the methods above check for existence, but rather accessibility. "? Could you please explain that in more detail for me? – John Oct 08 '21 at 08:18
  • @PherricOxide `ifstream f(name.c_str())` tries to create an empty file if it does not exist on `Ubuntu16.04`. `ifstream f(name.c_str(), std::ifstream::in)` works for me other than `ifstream f(name.c_str())` . How do you think about it? – John Oct 08 '21 at 08:20
  • @joh The first 2 tests attempt to open the file for read access, the 3rd test explicitly checks for access permissions, and the final test requires execute (search) permission on all directories that lead to the file. In all cases, failure to *access* the file is then reported as *"the file doesn't exist"*, which may or may not be true. – IInspectable Oct 08 '21 at 11:56
  • What about fs::exists() ? – Pedro77 Jul 04 '22 at 15:05
  • downvoting. this answer was probably acceptable before C++17 but it definitly not deserved to be the top ranked anymore. – sandwood Nov 17 '22 at 10:20
279

Remark : in C++14 and as soon as the filesystem TS will be finished and adopted, the solution will be to use:

std::experimental::filesystem::exists("helloworld.txt");

and since C++17, only:

std::filesystem::exists("helloworld.txt");
Community
  • 1
  • 1
Vincent
  • 57,703
  • 61
  • 205
  • 388
137

I use this piece of code, it works OK with me so far. This does not use many fancy features of C++:

bool is_file_exist(const char *fileName)
{
    std::ifstream infile(fileName);
    return infile.good();
}
harryngh
  • 1,789
  • 1
  • 13
  • 6
50

For those who like boost:

boost::filesystem::exists(fileName)

or, since ISO C++17:

std::filesystem::exists(fileName)
Yun
  • 3,056
  • 6
  • 9
  • 28
anhoppe
  • 4,287
  • 3
  • 46
  • 58
  • 7
    Boost is usually extremely slow. – Serge Rogatch Aug 27 '16 at 15:58
  • 7
    For most applications a file exists check is not performance critical – anhoppe Oct 19 '16 at 09:49
  • 1
    If performance is not critical, then there is also no point in using C++: a more high-level language like Java would give more productivity. So Boost effectively nullifies the point of using C++. – Serge Rogatch Oct 19 '16 at 15:31
  • 38
    Not all aspects of a high performance application require optimization. For example, reading the command line or a config file can be complex and may not require speed, though the application itself may require the performance advantages of C++. Avoiding Boost in such cases constitutes wheel reinvention, high on the anti-pattern list. – evoskuil Oct 20 '16 at 16:14
  • @evoskull - Boost may not be able to meet requirement. I've audited it three times in the past. It generated so many findings we could not use it. – jww Nov 01 '17 at 19:58
  • 7
    @SergeRogatch boost::filesystem::exists is not extremely slow. See my benchmark results for detail information. – hungptit May 05 '18 at 04:54
  • 8
    "Boost is usually extremely slow" -- this is false, and it isn't even clear what the scope of the claim is ... Boost contains many packages by different authors but is vetted for high quality. "For most applications a file exists check is not performance critical" -- the OP specifically asked for speed due to checking a very large number of files. "If performance is not critical, then there is also no point in using C++" -- another erroneous comment (and off topic). Most software is written in *shops* and is part of a *system* that mandates language choice. – Jim Balter Oct 01 '18 at 08:06
30

It depends on where the files reside. For instance, if they are all supposed to be in the same directory, you can read all the directory entries into a hash table and then check all the names against the hash table. This might be faster on some systems than checking each file individually. The fastest way to check each file individually depends on your system ... if you're writing ANSI C, the fastest way is fopen because it's the only way (a file might exist but not be openable, but you probably really want openable if you need to "do something on it"). C++, POSIX, Windows all offer additional options.

While I'm at it, let me point out some problems with your question. You say that you want the fastest way, and that you have thousands of files, but then you ask for the code for a function to test a single file (and that function is only valid in C++, not C). This contradicts your requirements by making an assumption about the solution ... a case of the XY problem. You also say "in standard c++11(or)c++(or)c" ... which are all different, and this also is inconsistent with your requirement for speed ... the fastest solution would involve tailoring the code to the target system. The inconsistency in the question is highlighted by the fact that you accepted an answer that gives solutions that are system-dependent and are not standard C or C++.

Community
  • 1
  • 1
Jim Balter
  • 16,163
  • 3
  • 43
  • 66
28

Without using other libraries, I like to use the following code snippet:

#ifdef _WIN32
   #include <io.h> 
   #define access    _access_s
#else
   #include <unistd.h>
#endif

bool FileExists( const std::string &Filename )
{
    return access( Filename.c_str(), 0 ) == 0;
}

This works cross-platform for Windows and POSIX-compliant systems.

Alex Huszagh
  • 13,272
  • 3
  • 39
  • 67
Viktor Liehr
  • 508
  • 4
  • 14
  • Does this work on Mac? I don't have a mac, but I would expect a mac to be able to include `unistd.h` also. Maybe the first `#ifdef` should be windows specific? – matth Aug 23 '16 at 20:58
  • 5
    Mac OSX is POSIX-compliant. – schaiba Jan 18 '18 at 12:27
  • This can and will fail for setuid/setgid processes: ["... The checks for accessibility (including directory permissions checked during pathname resolution) shall be performed using the real user ID in place of the effective user ID and the real group ID in place of the effective group ID."](https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html) – Andrew Henle Sep 06 '21 at 21:07
25

Same as suggested by PherricOxide but in C

#include <sys/stat.h>
int exist(const char *name)
{
  struct stat   buffer;
  return (stat (name, &buffer) == 0);
}
O'Neil
  • 3,790
  • 4
  • 16
  • 30
Ramon La Pietra
  • 609
  • 7
  • 13
11

I need a fast function that can check if a file is exist or not and PherricOxide's answer is almost what I need except it does not compare the performance of boost::filesystem::exists and open functions. From the benchmark results we can easily see that :

  • Using stat function is the fastest way to check if a file is exist. Note that my results are consistent with that of PherricOxide's answer.

  • The performance of boost::filesystem::exists function is very close to that of stat function and it is also portable. I would recommend this solution if boost libraries is accessible from your code.

Benchmark results obtained with Linux kernel 4.17.0 and gcc-7.3:

2018-05-05 00:35:35
Running ./filesystem
Run on (8 X 2661 MHz CPU s)
CPU Caches:
  L1 Data 32K (x4)
  L1 Instruction 32K (x4)
  L2 Unified 256K (x4)
  L3 Unified 8192K (x1)
--------------------------------------------------
Benchmark           Time           CPU Iterations
--------------------------------------------------
use_stat          815 ns        813 ns     861291
use_open         2007 ns       1919 ns     346273
use_access       1186 ns       1006 ns     683024
use_boost         831 ns        830 ns     831233

Below is my benchmark code:

#include <string.h>                                                                                                                                                                                                                                           
#include <stdlib.h>                                                                                                                                                                                                                                           
#include <sys/types.h>                                                                                                                                                                                                                                        
#include <sys/stat.h>                                                                                                                                                                                                                                         
#include <unistd.h>                                                                                                                                                                                                                                           
#include <dirent.h>                                                                                                                                                                                                                                           
#include <fcntl.h>                                                                                                                                                                                                                                            
#include <unistd.h>                                                                                                                                                                                                                                           

#include "boost/filesystem.hpp"                                                                                                                                                                                                                               

#include <benchmark/benchmark.h>                                                                                                                                                                                                                              

const std::string fname("filesystem.cpp");                                                                                                                                                                                                                    
struct stat buf;                                                                                                                                                                                                                                              

// Use stat function                                                                                                                                                                                                                                          
void use_stat(benchmark::State &state) {                                                                                                                                                                                                                      
    for (auto _ : state) {                                                                                                                                                                                                                                    
        benchmark::DoNotOptimize(stat(fname.data(), &buf));                                                                                                                                                                                                   
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_stat);                                                                                                                                                                                                                                          

// Use open function                                                                                                                                                                                                                                          
void use_open(benchmark::State &state) {                                                                                                                                                                                                                      
    for (auto _ : state) {                                                                                                                                                                                                                                    
        int fd = open(fname.data(), O_RDONLY);                                                                                                                                                                                                                
        if (fd > -1) close(fd);                                                                                                                                                                                                                               
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_open);                                  
// Use access function                                                                                                                                                                                                                                        
void use_access(benchmark::State &state) {                                                                                                                                                                                                                    
    for (auto _ : state) {                                                                                                                                                                                                                                    
        benchmark::DoNotOptimize(access(fname.data(), R_OK));                                                                                                                                                                                                 
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_access);                                                                                                                                                                                                                                        

// Use boost                                                                                                                                                                                                                                                  
void use_boost(benchmark::State &state) {                                                                                                                                                                                                                     
    for (auto _ : state) {                                                                                                                                                                                                                                    
        boost::filesystem::path p(fname);                                                                                                                                                                                                                     
        benchmark::DoNotOptimize(boost::filesystem::exists(p));                                                                                                                                                                                               
    }                                                                                                                                                                                                                                                         
}                                                                                                                                                                                                                                                             
BENCHMARK(use_boost);                                                                                                                                                                                                                                         

BENCHMARK_MAIN();   
hungptit
  • 1,414
  • 15
  • 16
10
inline bool exist(const std::string& name)
{
    ifstream file(name);
    if(!file)            // If the file was not found, then file is 0, i.e. !file=1 or true.
        return false;    // The file was not found.
    else                 // If the file was found, then file is non-0.
        return true;     // The file was found.
}
Sam
  • 7,252
  • 16
  • 46
  • 65
LOLOLOL
  • 125
  • 1
  • 3
  • 24
    If you're really going to do that, just "return (bool)file" rather than using an if/else branch. – Nik Haldimann Aug 20 '14 at 22:17
  • Don't forget to close the file in the event of the true case. That's a type of memory leak if you leave the file open for the entire runtime of the program, not to mention it may lock your file so that you can't read it after knowing that its exists.. add: file.close() to second else. – Bimo Jul 18 '18 at 23:38
  • 2
    on second thought maybe you don't need to explicitly close it... I forgot that ifstream is an RAII (Resource Acquisition Is Initialization )...and will clean itself up as it goes out of scope from the destructor... what can I say... I get brainwashed by garbage collector languages these days... – Bimo Jul 18 '18 at 23:41
  • @BillMoore Your second comment is correct; many other comments on this page have noted `close()` is not necessary. – Keith M Aug 20 '18 at 21:36
  • 1
    This checks accessibility, not existence. For example, if the file exists, but cannot be accessed due to access rights, it will return false, mistakenly claiming that the file does not exist. – SasQ Feb 16 '19 at 11:27
7

Another 3 options under windows:

1

inline bool exist(const std::string& name)
{
    OFSTRUCT of_struct;
    return OpenFile(name.c_str(), &of_struct, OF_EXIST) != INVALID_HANDLE_VALUE && of_struct.nErrCode == 0;
}

2

inline bool exist(const std::string& name)
{
    HANDLE hFile = CreateFile(name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile != NULL && hFile != INVALID_HANDLE)
    {
         CloseFile(hFile);
         return true;
    }
    return false;
}

3

inline bool exist(const std::string& name)
{
    return GetFileAttributes(name.c_str()) != INVALID_FILE_ATTRIBUTES;
}
ravin.wang
  • 1,122
  • 1
  • 9
  • 26
  • OpenFile is ANSI only and [limited to 128 characters](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365430(v=vs.85).aspx). – David Bremner Mar 13 '15 at 22:56
  • 6
    The `GetFileAttributes` version is basically the canonical way to do it in Windows. – Felix Dombek Nov 20 '15 at 17:50
  • I know this is old but what will happen in 3rd case when user has the ability to read the file but is not allowed to read the file attributes? – Quest Dec 25 '18 at 11:12
6

You may also do bool b = std::ifstream('filename').good();. Without the branch instructions(like if) it must perform faster as it needs to be called thousands of times.

  • As the accepted answer shows, this is untrue. Any serious compiler will probably emit the same code whether you put in the *if* or not. Compared to the plain-C variants, constructing the ifstream object (even if on the stack) incurs additional overhead. – minexew Feb 07 '16 at 20:06
6

If you need to distinguish between a file and a directory, consider the following which both use stat which the fastest standard tool as demonstrated by PherricOxide:

#include <sys/stat.h>
int FileExists(char *path)
{
    struct stat fileStat; 
    if ( stat(path, &fileStat) )
    {
        return 0;
    }
    if ( !S_ISREG(fileStat.st_mode) )
    {
        return 0;
    }
    return 1;
}

int DirExists(char *path)
{
    struct stat fileStat;
    if ( stat(path, &fileStat) )
    {
        return 0;
    }
    if ( !S_ISDIR(fileStat.st_mode) )
    {
        return 0;
    }
    return 1;
}
Valid
  • 767
  • 7
  • 14
5

You can use std::ifstream, funcion like is_open, fail, for example as below code (the cout "open" means file exist or not):

enter image description here

enter image description here

cited from this answer

Jayhello
  • 5,931
  • 3
  • 49
  • 56
4

All of the other answers focus on individually checking every file, but if the files are all in one directory (folder), it might be much more efficient to just read the directory and check for the existence of every file name you want.

This might even be more efficient even if the files are spread across several directories, depends on the exact ratio of directories to files. Once you start getting closer to each target file being in its own directory, or there being lots of other files in the same directories which you don't want to check for, then I'd expect it to finally tip over into being less efficient than checking each file individually.

A good heuristic: working on a bunch of data you already have is much faster than asking the operating system for any amount of data. System call overhead is huge relative to individual machine instructions. So it is almost always going to be faster to ask the OS "give me the entire list of files in this directory" and then to dig through that list, and slower to ask the OS "give me information on this file", "okay now give me information on this other file", "now give me information on ...", and so on.

Every good C library implements its "iterate over all files in a directory" APIs in an efficient way, just like buffered I/O - internally it reads up a big list of directory entries from the OS at once, even though the APIs look like asking the OS for each entry individually.


So if I had this requirement, I would

  1. do everything possible to encourage the design and usage so that all the files were in one folder, and no other files were in that folder,
  2. put the list of file names that I need to be present into a data structure in memory that has O(1) or at least O(log(n)) lookup and delete times (like a hash map or a binary tree),
  3. list the files in that directory, and "check off" (delete) each one as I went from the "list" (hash map or binary tree) in memory.

Except depending on the exact use case, maybe instead of deleting entries from a hash map or tree, I would keep track of a "do I have this file?" boolean for each entry, and figure out a data structure that would make it O(1) to ask "do I have every file?". Maybe a binary tree but the struct for each non-leaf node also has a boolean that is a logical-and of the booleans of its leaf nodes. That scales well - after setting a boolean in a leaf node, you just walk up the tree and set each node's "have this?" boolean with the && of its child node's boolean (and you don't need to recurse down those other child nodes, since if you're doing this process consistently every time you go to set one of the leaves to true, they will be set to true if and only if all of their children are.)


Sadly, there is no standard way to do it until C++17.

C++17 got std::filesystem::directory_iterator.

Of course there is a corresponding boost::filesystem::directory_iterator which I presume will work in older versions of C++.

The closest thing to a standard C way is opendir and readdir from dirent.h. That is a standard C interface, it's just standardized in POSIX and not in the C standard itself. It comes is available out-of-the-box on Mac OS, Linux, all the BSDs, other UNIX/UNIX-like systems, and any other POSIX/SUS system. For Windows, there is a dirent.h implementation that you just have to download and drop into your include path.

However, since you're looking for the fastest way, you might want to look beyond the portable/standard stuff.

On Linux, you might be able to optimize your performance by manually specifying the buffer size with the raw system call getdents64.

On Windows, after a bit of digging, it looks like for maximum performance you want to use FindFirstFileEx with FindExInfoBasic and FIND_FIRST_EX_LARGE_FETCH when you can, which a lot of the open source libraries like the above dirent.h for Windows don't seem to do. But for code that needs to work with stuff older than the last couple Windows versions, you might as well just use the straightforward FindFirstFile without the extra flags.

Plan 9 won't be covered by any of the above, and there you'll want dirread or dirreadall (the latter if you can safely assume you have enough memory for the entire directory contents). If you want more control over the buffer size for performance use plain read or read and decode the directory entry data - they're in a documented machine-independent format and I think there's helper functions provided.

I don't know about any other operating systems.


I might edit this answer with some tests later. Others are welcome to edit in test results as well.

mtraceur
  • 3,254
  • 24
  • 33
3
all_of (begin(R), end(R), [](auto&p){ exists(p); })

where R is your sequence of path-like things, and exists() is from the future std or current boost. If you roll your own, keep it simple,

bool exists (string const& p) { return ifstream{p}; }

The branched solution isn't absolutely terrible and it won't gobble file descriptors,

bool exists (const char* p) {
    #if defined(_WIN32) || defined(_WIN64)
    return p && 0 != PathFileExists (p);
    #else
    struct stat sb;
    return p && 0 == stat (p, &sb);
    #endif
}
John
  • 131
  • 1
  • 2
  • `PathFileExists` is limited to `MAX_PATH` (260) characters; `GetFileAttributes` doesn't have this limitation. – Felix Dombek Nov 20 '15 at 17:55
  • `GetFileAttributes` is limited to MAX_PATH as well. The docs describe a workaround **if** you use absolute paths, unicode, and prepend a special prefix string to the path name. I think we're off on a tangent with the Windows-specific responses anyway. – John Nov 22 '15 at 18:25
  • 1
    `GetFileAttributesW` doesn't have the limitation. – Laurie Stearn Mar 19 '18 at 05:06
3

In C++17 :

#include <experimental/filesystem>

bool is_file_exist(std::string& str) {   
    namespace fs = std::experimental::filesystem;
    fs::path p(str);
    return fs::exists(p);
}
3

well there's an even easier way

#include <fstream>
#include <iostream>

void FileExists(std::string myfile){
std::ifstream file(myfile.c_str());

if (file) {
    std::cout << "file exists" << std::endl;
}
else {
    std::cout << "file doesn't exist" << std::endl;
}
}

int main() {
FileExists("myfile.txt");

return 0;
}
jack chyna
  • 83
  • 4
  • 1
    This doesn’t work properly if the file exists but the user doesn’t have read permissions. Additionally, it was already covered by a different answer. – Sneftel Sep 06 '21 at 07:21
1

Here is a simple example!

#include <iostream>
#include <fstream>
using namespace std;
    
void main(){
   SearchFile("test.txt");
}

bool SearchFile(const char *file)
{
   ifstream infile(file);
   if (!infile.good())
   {
    // If file is not there
    exit(1);
   }
}
0

Using MFC it is possible with the following

CFileStatus FileStatus;
BOOL bFileExists = CFile::GetStatus(FileName,FileStatus);

Where FileName is a string representing the file you are checking for existance

O'Neil
  • 3,790
  • 4
  • 16
  • 30
0

there is only one faster way to check if the file exists and if you have permission to read it the way is using C language wish is faster and can be used also in any version in C++

solution: in C there is a library errno.h which has an external (global) integer variable called errno which contains a number that can be used to recognize the type of error

    #include <stdio.h>
    #include <stdbool.h>
    #include <errno.h>

    bool isFileExist(char fileName[]) {
        FILE *fp = fopen(fileName, "r");
        if (fp) {
            fclose(fp);
            return true;
        }
        return errno != ENOENT;
    }

    bool isFileCanBeRead(char fileName[]) {
        FILE *fp = fopen(fileName, "r");
        if (fp) {
            fclose(fp);
            return true;
        }
        return errno != ENOENT && errno != EPERM;
    }
0

The fastest and the safest way to test for file existence is not to separately/explicitly test for it at all. That is, see if you can find a way to replace the ordinary

if(exists(file)) {                           /* point A */
    /* handle existence condition */
    return;
}

do_something_with(file);                     /* point B */

with the improved

r = do_something_with_unless_exists(file);

if(r == 0)
    success;
else if(errno == EEXIST)
    /* handle existence condition */
else
    /* handle other error */

Besides being faster, this eliminates the race condition (specifically, "TOC/TOU") inherent in the first solution, namely the possibility that the file comes into existence between point A and point B.

Obviously the second solution presupposes the existence of an atomic way to do the do_something_with_unless_exists operation. Often there is a way, but sometimes you have to hunt around for it.

  • Creating a file: call open() with O_CREAT and O_EXCL.

  • Creating a file in pure C, if you have C11: call fopen() with "wx". (I only just learned about this one yesterday.)

  • Making a directory: just call mkdir() and check for errno == EEXIST afterwards.

  • Acquiring a lock: any locking system worth its salt already has an atomic acquire-the-lock-as-long-as-nobody-else-has-it primitive.

(There are others, but those are the ones I can think of just now.)

[Footnote: In the early days of Unix, there were no specific, dedicated facilities made available to ordinary processes to do locking, so if you wanted to set up a mutex, this was typically implemented by creating a certain empty directory, since the mkdir syscall has always had the ability to fail or succeed based on prior existence or nonexistence, atomically.]

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
-1

Detecting if a file exists in windows.

bool DoesExistFile(std::wstring filePath)
{
    bool result = true;

    HANDLE fileHandle = CreateFile(
        filePath.c_str(),
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    if ((fileHandle != NULL) && (fileHandle != INVALID_HANDLE_VALUE))
        CloseHandle(fileHandle);
    else
    {
        DWORD error = GetLastError();

        if ((error == ERROR_FILE_NOT_FOUND) || (error == ERROR_PATH_NOT_FOUND))
            result = false;
    }

    return result;
}
Juan Carlos
  • 131
  • 1
  • 6
  • 1
    This would work if there were no access control in Windows. As it stands, access control is the core security primitive in Windows. Regardless, if you want fast without as many false positives, use `GetFileAttributes` (see [Superstition: Why is GetFileAttributes the way old-timers test file existence?](https://devblogs.microsoft.com/oldnewthing/20071023-00/?p=24713)). – IInspectable Sep 18 '21 at 09:12
  • @IInspectable thank you for your comment and the link, I really appreciate it. In my specific case, working with [Cloud Filter API](https://learn.microsoft.com/en-us/windows/win32/cfapi/cloud-filter-reference), this was the only way that worked to check the existing parent folder of a deleted placeholder file. I tested with `stat` and `GetFileAttributes` functions but they didn't work. – Juan Carlos Sep 18 '21 at 17:14
  • The CF API is a virtualization on top of the filesystem. This question is asking about the filesystem, not a virtualization built on top of it. – IInspectable Sep 18 '21 at 20:24
  • Anyway, I hope to help someone that faces my problem or something similar. – Juan Carlos Sep 18 '21 at 20:44
  • In that case you should publish a new question where this proposed answer applies. You can then [answer your own question](https://stackoverflow.com/help/self-answer). – IInspectable Sep 19 '21 at 15:19
-6

Although there are several ways to do this the most efficient solution to your problem would probably be to use one of the fstream's predefined method such as good(). With this method you can check whether the file you've specified exist or not.

fstream file("file_name.txt");

if (file.good()) 
{
    std::cout << "file is good." << endl;
}
else 
{
    std::cout << "file isnt good" << endl;
}

I hope you find this useful.

miksiii
  • 2,426
  • 26
  • 22
  • 5
    This code will create the file if it doesn't exist, so the result will always be true. You need to either use ifstream, or set the openmode parameter correctly. – Lubo Antonov Jul 27 '16 at 21:14