What's the Best Way to Check If a File Exists in C++? (Cross Platform)

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

Use boost::filesystem:

#include <boost/filesystem.hpp>

if ( !boost::filesystem::exists( "myfile.txt" ) )
{
std::cout << "Can't find my file!" << std::endl;
}

Check if object at a path is a file or directory cross platform?

Unfortunately in C there is not an easy, portable or direct way to do this.

To that though, here's a bit of C code I converted from some C++ code I wrote for a cross platform library that can be used to check if a file or directory exists:

#include <sys/stat.h>
#include <sys/types.h>
#if defined(OS_WIN)
#include <windows.h>
#else
#include <dirent.h> // for *Nix directory access
#include <unistd.h>
#endif

bool file_exists(const char* file)
{
if (file == NULL) { return false; }
#if defined(OS_WIN)
#if defined(WIN_API)
// if you want the WinAPI, versus CRT
if (strnlen(file, MAX_PATH+1) > MAX_PATH) {
// ... throw error here or ...
return false;
}
DWORD res = GetFileAttributesA(file);
return (res != INVALID_FILE_ATTRIBUTES &&
!(res & FILE_ATTRIBUTE_DIRECTORY));
#else
// Use Win CRT
struct stat fi;
if (_stat(file, &fi) == 0) {
#if defined(S_ISSOCK)
// sockets come back as a 'file' on some systems
// so make sure it's not a socket or directory
// (in other words, make sure it's an actual file)
return !(S_ISDIR(fi.st_mode)) &&
!(S_ISSOCK(fi.st_mode));
#else
return !(S_ISDIR(fi.st_mode));
#endif
}
return false;
#endif
#else
struct stat fi;
if (stat(file, &fi) == 0) {
#if defined(S_ISSOCK)
return !(S_ISDIR(fi.st_mode)) &&
!(S_ISSOCK(fi.st_mode));
#else
return !(S_ISDIR(fi.st_mode));
#endif
}
return false;
#endif
}

bool dir_exists(const char* folder)
{
if (folder == NULL) { return false; }
#if defined(OS_WIN)
#if defined(WIN_API)
// if you want the WinAPI, versus CRT
if (strnlen(folder, MAX_PATH+1) > MAX_PATH) {
// ... throw error here or ...
return false;
}
DWORD res = GetFileAttributesA(folder);
return (res != INVALID_FILE_ATTRIBUTES &&
(res & FILE_ATTRIBUTE_DIRECTORY));
#else
struct stat fi;
if (_stat(folder, &fi) == 0) {
return (S_ISDIR(fi.st_mode));
}
return false;
#endif
#else
struct stat fi;
if (stat(folder, &fi) == 0) {
return (S_ISDIR(fi.st_mode));
}
return false;
#endif
}

To build it for Windows, simply define OS_WIN for that build; additionally, if you want to stick with full WinAPI, versus using the Windows CRT, you can define WIN_API.

To check if the given path is a file or directory, you can use something like the following code:

bool is_file(const char* path)
{
return file_exists(path) && !dir_exists(path);
}

bool is_dir(const char* path)
{
return dir_exists(path) && !file_exists(path);
}

You can obviously change the code to whatever suits your needs, but that should get you in the direction you need to build your code on Windows/macOS/*nix systems.

I hope that can help.

What's the best way to check if a file exists in C?

Look up the access() function, found in unistd.h. You can replace your function with

if (access(fname, F_OK) == 0) {
// file exists
} else {
// file doesn't exist
}

Under Windows (VC) unistd.h does not exist. To make it work it is necessary to define:

#ifdef WIN32
#include <io.h>
#define F_OK 0
#define access _access
#endif

You can also use R_OK, W_OK, and X_OK in place of F_OK to check for read permission, write permission, and execute permission (respectively) rather than existence, and you can OR any of them together (i.e. check for both read and write permission using R_OK|W_OK)

Update: Note that on Windows, you can't use W_OK to reliably test for write permission, since the access function does not take DACLs into account. access( fname, W_OK ) may return 0 (success) because the file does not have the read-only attribute set, but you still may not have permission to write to the file.

Fastest way to check if a file exists using standard C++/C++11,14,17/C?

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,



























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

How do I check whether a file exists in C++ for a Windows program?

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.

Fast way to check if file pointer points to a valid file

If a call to fopen has succeeded, but you want to know whether you've just opened a file or something else, I know of two general approaches:

  1. Use fstat on the file descriptor (or stat on the same pathname you just opened), then inspect the mode bits.

  2. Attempt to seek on the file descriptor. If this works as expected it's probably a file; if it doesn't it's a pipe or a socket or something like that.

The code for (1) might look like

struct stat st;
fstat(fileno(fp), &st);
if(st.st_mode & S_IFMT) == S_IFREG)
/* it's a regular file */

To perform (2) I normally seek to offset 1, then test to see what offset I'm at. If I'm at 1, it's a seekable file, and I rewind to 0 for the rest of the program. But if I'm still at 0, it's not a seekable file. (And of course I do this once, right after I open the file, and record the result in my own flag associated with the open file, so the performance hit is minimal.)

Will errno == ENOENT be a sufficient check to check if file exists in C?

fopen needs to do lots of stuff and checking before the file is opened. ENOENT implies that the file does not exist, but file not existing does not imply ENOENT.

It is possible for a file to not exist and you to get another error, such as EACCES for not being able to read the parent directory for example.


On the other hand, ENOENT from fopen does not mean that some other process couldn't have created the file even before fopen returns or before you're inspecting the errno and so on; this is the reason why C11 added the x flag for opening a file for writing in exclusive mode - failing if the file already exists.


To sum it up: if you get ENOENT, the file did not exist when you tried opening it. If you get some other error, then each other error code would belong to one of 3 these classes - that it is certain that either

  • the file existed, or
  • it cannot have existed
  • or it might have existed at the time

at the time of opening. It is up to you and your required logic how you'd handle these other errors. A simple way would be to refuse to continue processing, reporting the error to the user.



Related Topics



Leave a reply



Submit