C#
.NET
File Handling
Programming
File.Exists

How to find out if a file exists in C / .NET?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In C# and .NET, the usual way to check whether a file exists is File.Exists(path). That answer is often enough for UI messages or optional configuration, but it is not a guarantee that the file will still be available when you try to open it a moment later.

That difference matters in real systems. File existence checks are simple, but correct file-handling code also needs to think about relative paths, permissions, and race conditions between the check and the actual file operation.

Start With File.Exists

For a basic check, use System.IO.File.Exists:

csharp
1using System;
2using System.IO;
3
4class Program
5{
6    static void Main()
7    {
8        string path = "config/appsettings.json";
9
10        if (File.Exists(path))
11            Console.WriteLine("File exists");
12        else
13            Console.WriteLine("File does not exist");
14    }
15}

This is the standard answer for simple flow control. If the file is optional, this may be all you need.

Normalize Paths Before Trusting the Result

A common source of confusion is the path itself. Relative paths depend on the process working directory, not on where your source file lives. It is often safer to normalize first:

csharp
1using System;
2using System.IO;
3
4static bool ExistsSafe(string rawPath)
5{
6    if (string.IsNullOrWhiteSpace(rawPath))
7        return false;
8
9    try
10    {
11        string fullPath = Path.GetFullPath(rawPath);
12        return File.Exists(fullPath);
13    }
14    catch (Exception ex) when (
15        ex is ArgumentException ||
16        ex is NotSupportedException ||
17        ex is PathTooLongException)
18    {
19        return false;
20    }
21}
22
23Console.WriteLine(ExistsSafe("./README.md"));

This avoids a lot of "it works locally but not on the server" confusion caused by unexpected working directories.

Avoid the Check-Then-Open Trap

The most important design issue is time-of-check versus time-of-use. A file can exist when you check it and then disappear, change, or become locked before you open it. For critical file access, open the file directly and handle errors:

csharp
1using System;
2using System.IO;
3
4static string ReadTextSafe(string path)
5{
6    try
7    {
8        using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
9        using var reader = new StreamReader(stream);
10        return reader.ReadToEnd();
11    }
12    catch (FileNotFoundException)
13    {
14        return "File not found";
15    }
16    catch (DirectoryNotFoundException)
17    {
18        return "Directory not found";
19    }
20    catch (UnauthorizedAccessException)
21    {
22        return "Access denied";
23    }
24    catch (IOException)
25    {
26        return "I/O unavailable";
27    }
28}

This pattern reflects the real runtime state instead of trusting an earlier existence check.

Distinguish Files From Directories

File.Exists only tells you about files. If the path may point to a directory, use Directory.Exists separately:

csharp
1using System;
2using System.IO;
3
4string filePath = "logs/app.log";
5string dirPath = "logs";
6
7Console.WriteLine(File.Exists(filePath));
8Console.WriteLine(Directory.Exists(dirPath));

This sounds obvious, but it is a frequent source of false negatives when paths are passed in from configuration.

Use Temporary Files in Tests

File existence logic is easy to test deterministically with temporary files:

csharp
1using System;
2using System.IO;
3
4string tempPath = Path.GetTempFileName();
5Console.WriteLine(File.Exists(tempPath));
6
7File.Delete(tempPath);
8Console.WriteLine(File.Exists(tempPath));

This is a good way to validate both the positive and negative paths without relying on machine-specific files.

Common Pitfalls

The biggest mistake is treating File.Exists as a durable guarantee before a later open or delete. It is only a moment-in-time observation.

Another common issue is relying on relative paths without controlling the working directory. Services, tests, and desktop apps often run with different current directories.

Developers also forget about permissions. A file may exist and still be inaccessible to the current process.

Finally, use the right API for the path type. A directory path passed to File.Exists returns false, which can make the problem look like a missing file when it is really the wrong path category.

Summary

  • Use File.Exists for simple existence checks in .NET.
  • Normalize paths when working across environments or with user input.
  • For important operations, open the file directly and handle exceptions instead of relying on a check-then-open pattern.
  • Use Directory.Exists when the path may refer to a folder.
  • Test existence logic with temporary files so the behavior stays predictable.

Course illustration
Course illustration

All Rights Reserved.