21

Possible Duplicate:
How can we check if a file Exists or not using Win32 program?

Which is the best method for checking for file existence:

Option1:

GetFileAttributes("C:\\MyFile.txt"); // from winbase.h
if(0xffffffff == GetFileAttributes("C:\\MyFile.txt"))
{
    //File not found
}

Option2:

std::string fileName("C:\\MyFile.txt" );
ifstream fin( fileName.c_str() );

if( fin.fail() )
{
    //File not found
}

Also if you think option 1 is the better method, can you tell me how to define 0xffffffff as a constant (I don't want to use #define)

Thanks

Community
  • 1
  • 1
Robben_Ford_Fan_boy
  • 8,494
  • 11
  • 64
  • 85
  • 1
    You might need a better understanding of the language of your choosing before digging into libraries. This however does not mean, that one does not learn from other peoples code (i.e. libraries). – Marcus Borkenhagen Dec 09 '10 at 23:03
  • 3
    The second one does not test whether the file exists; it tests whether the fine can be opened. (The first one might be the same; I don't know off the top of my head what the behavior of `GetFileAttributes` is.) – James McNellis Dec 09 '10 at 23:03
  • maybe here too: http://stackoverflow.com/questions/2903360/how-to-check-whether-a-file-exists-in-c-drive-using-vc – karlphillip Dec 09 '10 at 23:05
  • Re Dups: Yep they are useful but I specifically wanted to know which of the options in my ques I should choose - the existing questions don't answer that. – Robben_Ford_Fan_boy Dec 10 '10 at 00:22

11 Answers11

31

Note that GetFileAttributes() may fail for other reasons than lack of existence (for example permissions issues). I would add a check on the error code for robustness:

GetFileAttributes("C:\\MyFile.txt"); // from winbase.h
if(INVALID_FILE_ATTRIBUTES == GetFileAttributes("C:\\MyFile.txt") && GetLastError()==ERROR_FILE_NOT_FOUND)
{
    //File not found
}
zdan
  • 28,667
  • 7
  • 60
  • 71
  • This does not handle the case when the path is a directory. Here's how: DWORD fileType = GetFileAttributes("C:\\Windows"); bool isDir = fileType & FILE_ATTRIBUTE_DIRECTORY; – Elliot Cameron Mar 21 '13 at 13:28
  • When I try this I find that many non-existent files are reported as existing. Although GetFileAttributes() returns INVALID..., GetLastError() does *not* report the NOT_FOUND error. – OldPeculier Aug 07 '13 at 14:51
  • 3
    @OldPeculier, Boost Filesystem uses the following error codes as indicators that the path does not exist: ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND, ERROR_INVALID_NAME, ERROR_INVALID_DRIVE, ERROR_NOT_READY, ERROR_INVALID_PARAMETER, ERROR_BAD_PATHNAME, ERROR_BAD_NETPATH. – Alex Che Aug 29 '14 at 07:17
  • We agree that just the `if` section is enough for the test? No need of both `GetFileAttributes` lines? – Sandburg Nov 24 '22 at 16:46
9

There are two things to consider here:

  1. Checking if the file exists via its attributes is potentially many orders of magnitude faster - If a file exists on a 'slow' file system - tape, network storage, cd etc then opening the file will involve an actual round trip to the files location. The files attributes on the other hand are queried and cached by the filesystem drivers when the directory is queried, so probing file attributes involves a once off directory enumeration cost - meaning far fewer round trips - which can be a significant saving if multiple "slow" files are being checked.

  2. However, the files attributes merely indicate that the file existed at the time the call was made. The file can be deleted, or you might not haver permissions to access it. If you are about to try and open the file anyway, it would be better to dispense with the file attributes check and actually try and open the file.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148
5

If you're targeting only Windows, option #1 is clearly the better of the two. Also, the constant you're looking for already exists in the Windows headers -- it's called INVALID_FILE_ATTRIBUTES.

casablanca
  • 69,683
  • 7
  • 133
  • 150
  • So is #define INVALID_FILE_ATTRIBUTES ((DWORD)-1) equivalent to 0xffffffff? It seems like 0xffffffff is defined already as #define INVALID_FILE_SIZE ((DWORD)0xFFFFFFFF)? – Robben_Ford_Fan_boy Dec 13 '10 at 12:05
  • @David Relihan: Yes, they're equivalent; since `DWORD` is unsigned, -1 is the same as the largest positive value which is 0xFFFFFFFF. – casablanca Dec 13 '10 at 15:17
5

How about use boost?

if (!boost::filesystem::exists("C:\\MyFile.txt"))
{
    ...
}

http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/index.htm

Inverse
  • 4,408
  • 2
  • 26
  • 35
5

The only robust way to check whether a file exists is to try to open it, and see if it succeeds or fails.

Any other method is a potential race condition. For example, GetFileAttributes can tell you if a file existed when you called the function, but that's not the same as whether it exists when you try to open it. It might have been deleted (or created) in the meantime.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • 1
    This is assuming you intend to open the file after checking whether it exists, which would indeed be silly. But there are reasons to check whether a file exists without ever opening it. – Karu May 03 '17 at 13:07
3

I would prefer the first. The second checks if the file can be opened, while a file might exist without you having the rights to open it.

You can use the INVALID_FILE_ATTRIBUTES constant.

GolezTrol
  • 114,394
  • 18
  • 182
  • 210
3

There's a nice shell utility function for that, PathFileExists.

Ofek Shilon
  • 14,734
  • 5
  • 67
  • 101
2

I'd opt to use the iostream because of its platform independence. True, you may be targeting Windows only, but it's never a bad move to use platform-independent libraries. If you're building a big project, you never know what that next phase will entail.

I'm not sure the code above is the best (or correct) way to check for file existence. Try this:

ifstream f;
f.open(str);

if (f.is_open()) {
  // read file
}
Courtney Christensen
  • 9,165
  • 5
  • 47
  • 56
2

I also like to confirm that the string isn't a directory:

DWORD attr = GetFileAttributes(file);
if(attr == INVALID_FILE_ATTRIBUTES || (attr & FILE_ATTRIBUTE_DIRECTORY))
    return false;   //  not a file
return true;
sean e
  • 11,792
  • 3
  • 44
  • 56
2

Back in the day, all we had was OpenFile (and we were GRATEFUL)

OFSTRUCT of = {0};
of.cBytes = sizeof(of);

HFILE hf = ::OpenFile("c:\\windows\\write.exe",&of,OF_EXIST);

if(hf > 0)
    printf("file exists"); 

return 0;
weloytty
  • 5,808
  • 5
  • 28
  • 35
1
#include <iostream>
#include <windows.h>
using namespace std;

bool FileExists(const TCHAR *fileName)
{
    DWORD       fileAttr;

    fileAttr = GetFileAttributes(fileName);
    if (0xFFFFFFFF == fileAttr && GetLastError()==ERROR_FILE_NOT_FOUND)
        return false;
    return true;
}

int main(int argc, char *argv[])
{


    if ( FileExists("testtt.txt"))
    {
      cout << "File exists \n";
    }
    else
    {
        cout << "File does not exist \n";

    }


  return 0;
}
Software_Designer
  • 8,490
  • 3
  • 24
  • 28