Skip to content

File and Directory Basics

Working with files and directories is one of the clearest ways to move from pure language syntax into real application behavior. File-system code deals with external state, permissions, missing paths, encoding, and failure cases that do not exist in isolated in-memory examples.

Original Microsoft Learn reference: File and stream I/O.

That makes it a good place to practice defensive programming.

Common file-system tasks

Practical C# programs often need to:

  • build file paths safely
  • create or read text files
  • enumerate directories
  • check whether files or directories exist
  • create folders if needed
  • handle missing resources and permission problems

A simple example

csharp
string path = Path.Combine(Environment.CurrentDirectory, "notes.txt");
File.WriteAllText(path, "Hello file");
Console.WriteLine(File.ReadAllText(path));

This shows the basic shape of file work:

  • create a path
  • write content
  • read content back

Why Path.Combine matters

You should usually avoid building file paths by hand with string concatenation.

csharp
string path = Path.Combine("data", "reports", "summary.txt");

Path.Combine is safer and clearer because it handles separators correctly for the platform.

A more practical example

csharp
string directory = Path.Combine(Environment.CurrentDirectory, "output");
Directory.CreateDirectory(directory);

string filePath = Path.Combine(directory, "log.txt");

File.AppendAllText(filePath, $"Started at {DateTime.Now}\n");
Console.WriteLine(File.ReadAllText(filePath));

This looks more like real application code because it creates a folder when needed and appends to a simple log file.

A mental model

mermaid
flowchart LR
    A["Build safe path"] --> B["Ensure directory exists"]
    B --> C["Read or write file"]
    C --> D["Handle failures if needed"]

Real file work is never only about the happy path.

File operations can fail

File-system code may fail for many reasons:

  • the file does not exist
  • the directory does not exist
  • the process lacks permission
  • the file is locked
  • the path is invalid
  • the disk or external storage is unavailable

That is why practical file code often needs validation and exception handling.

Reading defensively

csharp
string path = Path.Combine(Environment.CurrentDirectory, "settings.json");

if (File.Exists(path))
{
    string content = File.ReadAllText(path);
    Console.WriteLine(content);
}
else
{
    Console.WriteLine("Settings file not found.");
}

This is not the only valid approach, but it shows the idea that external resources require deliberate handling.

Files versus directories

It helps to keep the API surfaces separate in your mind:

  • File is for file-specific operations
  • Directory is for folder-specific operations
  • Path is for path construction and inspection

These types are often used together.

Practical guidance

Good file-system code usually:

  • uses Path.Combine instead of manual path strings
  • validates assumptions about file existence when appropriate
  • handles exceptions from external failures
  • avoids hard-coded machine-specific paths when possible
  • thinks about encoding, overwriting, and append behavior deliberately

Common beginner mistakes

  • Concatenating paths with raw string separators.
  • Assuming files always exist.
  • Ignoring permission or lock failures.
  • Treating file-system code like ordinary in-memory logic with no environmental risk.

Summary

  • file and directory code brings external state into your program
  • Path, File, and Directory each play different roles
  • practical code should assume file operations can fail
  • Path.Combine is the normal safe way to build paths
  • defensive checks and error handling matter much more here than in toy examples

Practice

Write a small program that creates a folder, writes a text file into it, then reads the file back.

As a second exercise, list three realistic reasons why that program could fail on another machine even if the code itself is correct.

Built with VitePress and published on GitHub Pages.