Question

How to Check If a File Exists in C++ and C

ccppfilestream

Question

I want to check whether a file exists, using standard C++11, C++14, C++17, or C. I may need to do this for thousands of files, so I want a reliable and efficient approach before processing them.

What can I write in this function?

inline bool exist(const std::string& name)
{
    /* SOMETHING */
}

Short Answer

By the end of this page, you will understand the standard ways to check whether a file exists in C++ and C, when to use each approach, and the practical limitations of existence checks. You will also see why std::filesystem::exists is the modern C++17 solution, what to do in C++11/C++14, and how C code commonly handles the same task.

Concept

Checking whether a file exists means asking the operating system whether a path currently refers to something on disk.

In modern C++17, the standard library provides this directly through std::filesystem::exists. In earlier standard C++ versions such as C++11 and C++14, there is no standard filesystem library, so developers often use std::ifstream to try opening the file. In C, a common standard approach is to call fopen and check whether it succeeds.

A key idea is that "exists" is only true at the moment you check. A file can be deleted, moved, or have its permissions changed immediately afterward. Because of that, in real programs it is often better to perform the operation you actually need and handle failure, rather than checking first and then acting.

Why this matters:

  • File processing tools need to avoid crashes when paths are missing.
  • Import scripts often validate input files before reading them.
  • Build tools, log readers, and backup utilities frequently work with many files.
  • Good file handling reduces bugs caused by missing files or permission problems.

So the real concept is not just "how do I check existence?" but also how to do file handling safely and idiomatically.

Mental Model

Think of a file path like a house address.

  • exists(path) asks: "Is there currently a building at this address?"
  • Opening a file asks: "Can I actually enter and use this building right now?"

Those are related, but not identical.

A house may exist but still be inaccessible because:

  • the door is locked (permission denied),
  • the address points to a different kind of place (directory instead of file),
  • the building is removed right after you check.

So an existence check is like a quick lookup, but the real test is whether the operation you need actually succeeds.

Take Quiz

Syntax and Examples

C++17: use std::filesystem::exists

#include <filesystem>
#include <string>

inline bool exist(const std::string& name)
{
    return std::filesystem::exists(name);
}

This is the standard C++17 solution. It clearly expresses your intent and works with filesystem paths.

You can also use std::filesystem::path directly:

#include <filesystem>

inline bool exist(const std::filesystem::path& path)
{
    return std::filesystem::exists(path);
}

That is often better in real code because filesystem APIs are designed around path.

C++11 / C++14: try opening the file

#include <fstream>
#include <string>

inline bool exist(const std::string& name)
{
    std::ifstream file(name);
    return file.good();
}

This is a common portable approach in pre-C++17 standard C++. If the file can be opened for reading, good() will be true.

A shorter version is:

#include <fstream>
#include <string>

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

C: use fopen

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

bool exist(const char* name)
{
    FILE* file = fopen(name, "r");
    if (file != NULL) {
        fclose(file);
        return true;
    }
    return false;
}

This is a standard C approach. If fopen succeeds, the path refers to something that can be opened for reading.

Important note

Opening a file is not exactly the same as checking whether it exists:

  • it may fail because of permissions,
  • the path may point to a directory,
  • the file may exist but still not be readable.

In C++17, std::filesystem::exists is more directly about existence.

Step by Step Execution

Consider this C++17 example:

#include <filesystem>
#include <iostream>

int main()
{
    std::string name = "report.txt";

    if (std::filesystem::exists(name)) {
        std::cout << "File exists\n";
    } else {
        std::cout << "File does not exist\n";
    }
}

Step by step:

  1. name stores the path string "report.txt".
  2. std::filesystem::exists(name) asks the operating system about that path.
  3. If the path currently exists, the function returns true.
  4. The if statement enters the first branch and prints File exists.
  5. Otherwise, it enters the else branch and prints File does not exist.

Now compare that with C++11 using ifstream:

#include <fstream>
#include <iostream>

int main()
{
    std::ifstream file("report.txt");

    if (file.good()) {
        std::cout << "Readable file found\n";
    } else {
        std::cout << "Could not open file\n";
    }
}

What happens here:

  1. The program tries to open report.txt for reading.
  2. If the open succeeds, the stream is in a good state.
  3. file.good() returns true.
  4. If opening fails, good() returns false.

This tells you more like "can I open it right now?" than purely "does it exist?".

Real World Use Cases

Input validation before processing

A batch script may receive a list of CSV files and check whether each path is valid before starting import.

Config file lookup

Applications often look for files such as:

  • config.json
  • .env
  • settings.ini

If the file does not exist, they may fall back to defaults.

Log and report generation

A program may check whether an output file already exists before overwriting it.

Asset loading

Games and media tools often verify that images, audio files, or templates are present before loading them.

Backup and synchronization tools

These tools compare expected files with actual files on disk and report missing items.

Take Quiz

Real Codebase Usage

In real projects, developers often do more than a simple existence check.

Prefer the real operation when possible

Instead of this:

if (std::filesystem::exists(path)) {
    std::ifstream in(path);
    // use file
}

many codebases prefer:

std::ifstream in(path);
if (!in) {
    // handle error
    return;
}
// use file

This avoids a check-then-act race condition.

Guard clauses

A common pattern is to return early when a required file is missing:

if (!std::filesystem::exists(path)) {
    return false;
}

Validation pipelines

When processing many files, code often validates each path first and stores missing ones in a list:

std::vector<std::string> missing;
for (const auto& path : paths) {
    if (!std::filesystem::exists(path)) {
        missing.push_back(path);
    }
}

Using path instead of raw strings

In larger codebases, this is common:

std::filesystem::path configPath = baseDir / "config.json";

That is safer and more expressive than manual string concatenation.

Error handling in C++17

Some filesystem functions may throw exceptions. In projects that avoid exceptions, developers may use overloads with std::error_code.

#include <filesystem>
#include <system_error>

std::error_code ec;
bool ok = std::filesystem::exists("data.txt", ec);
if (ec) {
    // handle filesystem error
}

This is useful when scanning large numbers of files and wanting explicit error reporting.

Common Mistakes

1. Assuming "exists" means "readable"

Broken assumption:

if (std::filesystem::exists(path)) {
    std::ifstream in(path);
    // assume success
}

Why this is a problem:

  • the file may exist but lack read permission,
  • it may be a directory,
  • it may disappear before opening.

Better:

std::ifstream in(path);
if (!in) {
    // handle failure
}

2. Forgetting to close FILE* in C

Broken code:

bool exist(const char* name)
{
    FILE* file = fopen(name, "r");
    return file != NULL;
}

Why this is wrong:

  • if fopen succeeds, the file handle leaks.

Correct version:

bool exist(const char* name)
{
    FILE* file = fopen(name, "r");
    if (file != NULL) {
        fclose(file);
        return true;
    }
    return false;
}

3. Using pre-checks unnecessarily

Beginners often write:

if (exist(path)) {
    std::ifstream in(path);
    // read file
}

This can be redundant. If you need the file for reading, just try to open it.

4. Forgetting C++17 support requirements

This code is valid only in C++17 and later:

#include <filesystem>
std::filesystem::exists("file.txt");

If your compiler is set to C++11 or C++14 mode, it will fail.

5. Confusing files and directories

std::filesystem::exists(path) returns true for both files and directories.

If you need a regular file specifically, use:

std::filesystem::is_regular_file(path)

6. Measuring the wrong kind of speed

The operating system call dominates the cost, not whether your wrapper function is inline.

This:

inline bool exist(const std::string& name)

usually does not create a meaningful speed difference compared with the filesystem access itself.

Comparisons

ApproachLanguage/VersionWhat it checksProsCons
std::filesystem::exists(path)C++17+Whether the path existsStandard, clear, directRequires C++17
std::ifstream(name).good()C++11/14Whether file can be opened for readingPortable in older standard C++Not a pure existence check
fopen(name, "r")CWhether file can be opened for readingStandard C, simpleMust close handle, not pure existence
Try actual operation directlyC++/CWhether the needed action succeedsSafest real-world patternDoes not give a separate pre-check

exists vs opening the file

QuestionBest tool
Does this path exist?std::filesystem::exists
Can I read this file right now?std::ifstream or fopen
Do I need to process the file safely?Try opening/processing and handle failure

exists vs is_regular_file

FunctionMeaning
exists(path)Something exists at the path
is_regular_file(path)A normal file exists at the path
is_directory(path)A directory exists at the path
Take Quiz

Cheat Sheet

C++17

#include <filesystem>
bool exists = std::filesystem::exists(path);

Use when you want to know whether a path exists.

C++11 / C++14

#include <fstream>
bool exists = std::ifstream(path).good();

Use when standard pre-C++17 C++ is required.

C

FILE* f = fopen(path, "r");
if (f) {
    fclose(f);
}

Important rules

  • exists(path) is available in standard C++17 and later.
  • exists(path) can return true for a directory too.
  • Use is_regular_file(path) if you need a normal file.
  • Opening a file checks accessibility, not just existence.
  • Prefer attempting the real operation when practical.
  • A file can change between checking and using it.

Good default choices

  • C++17+: std::filesystem::exists
  • C++11/14: std::ifstream(path).good()
  • C: fopen and check for NULL

Safer pattern when reading

std::ifstream in(path);
if (!in) {
    // handle error
}

If you need a regular file in C++17

if (std::filesystem::exists(path) && std::filesystem::is_regular_file(path)) {
    // safe to treat as a normal file path
}

FAQ

Is std::filesystem::exists the standard C++ way?

Yes. It is the standard solution in C++17 and later.

What should I use in C++11 or C++14?

A common standard approach is std::ifstream(path).good() to test whether the file can be opened for reading.

Is checking existence before opening a file always a good idea?

No. In many cases, it is better to open the file directly and handle failure. That avoids check-then-act issues.

Does exists() check only regular files?

No. It checks whether the path exists at all, which includes directories and other filesystem objects.

How do I check that the path is a normal file in C++17?

Use std::filesystem::is_regular_file(path).

Is ifstream(...).good() exactly the same as file existence?

No. It means the file stream is usable after opening, which depends on permissions and file type too.

Does making the function inline make the file check much faster?

Usually no. The expensive part is the filesystem access, not the function call.

What if I need to check thousands of files?

Use a simple loop and keep the logic clear. If you need only readability or processing, often it is best to try the real operation and collect failures.

Take Quiz

Mini Project

Description

Build a small file validator that checks a list of file paths and reports which ones are missing. This is a practical example of validating input before starting a batch process, such as importing data files or checking required resources.

Goal

Create a program that loops through several file paths and prints whether each file exists, along with a final count of missing files.

Requirements

  • Read or define a list of file paths to validate.
  • Check each path using a standard C++ approach.
  • Print a message for each path indicating whether it exists.
  • Count how many paths are missing.
  • Print a final summary at the end.
Take Quiz

Keep learning

Related questions

View more