3

This is for a Windows-only program so portable code is not an issue.

I need simply:

bool DoesFileExist( LPWSTR lpszFilename )
{
    // ...
}
Jarrod Dixon
  • 15,727
  • 9
  • 60
  • 72
Joe
  • 16,328
  • 12
  • 61
  • 75

12 Answers12

15

According to the venerable Raymond Chen, you should use GetFileAttributes if you're superstitious.

efotinis
  • 14,565
  • 6
  • 31
  • 36
  • 2
    interestingly, it looks like _access() is actually just a wrapper around GetFileAttributes() too – Jay Nov 27 '08 at 07:03
  • @Jay: That's right, since the whole C library is basically implemented in the Windows API. – efotinis Nov 27 '08 at 11:56
  • 1
    The only difference between superstition and best practices is if you remember why you do it – dlanod Oct 27 '09 at 23:16
  • +1 for mentioning Raymond. No matter what he said, he is always a good source of information – elcuco Jan 21 '10 at 22:58
9

What’s the best way to check if a file exists in C++? (cross platform)

Use _access or stat.

Community
  • 1
  • 1
Rob
  • 76,700
  • 56
  • 158
  • 197
  • Hey that's cool! I didn't realize you could use those functions on Windows. – kgriffs Nov 26 '08 at 20:45
  • They form part of the C runtime (CRT). Visual Studio lets you link to this statically (.lib) or dynamically (in which case a DLL would need to be shipped with your app). I can't think of a reason not to statically link. – Rob Nov 26 '08 at 21:26
7

This is a bit more of a complex question. There is no 100% way to check for existence of a file. All you can check is really "exstistence of a file that I have some measure of access to." With a non-super user account, it's very possible for a file to exist that you have no access to in such a way that access checks will not reveal the existincae of an file.

For instance. It's possible to not have access to a particular directory. There is no way then to determine the existence of a file within that directory.

That being said, if you want to check for the existence of a file you have a measure of access to use one of the following: _stat, _stat64, _stati64, _wstat, _wstat64, _wstati64

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
6

GetFileAttributes is what you're looking for. If it returns a value that is not INVALID_FILE_ATTRIBUTES the file exists.

Walter Bright
  • 4,277
  • 1
  • 23
  • 28
4

Open it. You can't reliably test if a file exists on a multi-tasking operating system. When you open it you can make sure it doesn't disappear.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Sometimes the goal of testing a file's existence is not to open it. It could be an actual test case. – Don Reba Feb 27 '10 at 20:47
3

Windows only? Use GetFileAttributes:

bool DoesFileExist( LPWSTR lpszFilename )
{
  return GetFileAttributes( lpszFilename ) != INVALID_FILE_ATTRIBUTES;
}

Or the more strict version (as per Szere Dyeri's comment):

bool DoesFileExist( LPWSTR lpszFilename )
{
  return ( ( GetFileAttributes( lpszFilename ) != INVALID_FILE_ATTRIBUTES )
         && ( GetLastError() == ERROR_FILE_NOT_FOUND ) );
}

Kornel Kisielewicz
  • 55,802
  • 15
  • 111
  • 149
1

Here's one of many options:

HANDLE handle = FindFirstFile(lpszFilename);
if (handle == INVALID_HANDLE_VALUE) 
    return false;
FindClose(handle);
return true;
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1

There are two common ways to do this in Windows code. GetFileAttributes, and CreateFile,

bool DoesFileExist(LPCWSTR pszFilename)
{
   DWORD dwAttrib = GetFileAttributes(pszFilename);
   if ( ! (dwAttrib & FILE_ATTRIBUTE_DEVICE) &&
        ! (dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
   {
      return true;
   }
   return false;
}

This will tell you a file exists, but but it won't tell you whether you have access to it. for that you need to use CreateFile.

bool DoesFileExist(LPCWSTR pszFilename)
{
    HANDLE hf = CreateFile(pszFilename,
                           GENERIC_READ,
                           FILE_SHARE_READ | FILE_SHARE_WRITE,
                           NULL,
                           OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);

    if (INVALID_HANDLE_VALUE != hf)
    {
        CloseHandle(hf);
        return true;
    }
    else if (GetLastError() == ERROR_SHARING_VIOLATION)
    {
        // should we return 'exists but you can't access it' here?
        return true;
    }

    return false;
}

But remember, that even if you get back true from one of these calls, the file could still not exist by the time you get around to opening it. Many times it's best to just behave as if the file exists and gracefully handle the errors when it doesn't.

John Knoeller
  • 33,512
  • 4
  • 61
  • 92
0

This should do it.

#include <fstream>

bool DoesFileExist( LPWSTR lpszFilename )
{
  ifstream fin;
  fin.open(lpszFilename.c_str(), ifstream::in);
  fin.close();
  return !fin.fail();
}
McAden
  • 13,714
  • 5
  • 37
  • 63
0

I use the FindFirstFile / FindNextFile API functions for this purpose.

Matt Dillard
  • 14,677
  • 7
  • 51
  • 61
0

In my experience, _access() is simple and fairly portable

#if defined(__MSDOS__) || defined(_Windows) || defined(_WIN32)
    bool file_exists =  _access(file_name,0) == 0;
#endif
#ifdef unix
    bool file_exists =  _access(file_name,F_OK) == 0;
#endif
Roger Nelson
  • 1,882
  • 2
  • 15
  • 21
-1

I usually use boost::filesystem. Has an exists() function. :)

jalf
  • 243,077
  • 51
  • 345
  • 550