File and Directory I/O Operations in C
File Input/Output (I/O) is an essential aspect of software
development that enables applications to persist, read, and manipulate
data on the file system. In C#, the System.IO namespace
provides two high-level, static classes—File and
Directory—that make common operations such as creating,
reading, writing, moving, and deleting files and folders straightforward
without requiring manual stream management. This guide provides a
direct, practical overview of how to use these classes for day-to-day
file system tasks.
The System.IO Namespace
To work with these classes, import the System.IO
namespace at the top of your C# file:
using System.IO;Working with the File Class
The static File class provides standard methods for
creating, copying, deleting, moving, and opening files, as well as
helpers to read and write text or bytes in a single call.
1. Writing to a File
You can write text, an array of strings, or byte arrays to a file. If the file does not exist, these methods create it; if it does exist, they overwrite the content by default.
string filePath = @"C:\temp\example.txt";
// Write a single string to a file
File.WriteAllText(filePath, "Hello, C# File I/O!");
// Write multiple lines from an array or collection
string[] lines = { "First line", "Second line", "Third line" };
File.WriteAllLines(filePath, lines);
// Append text to an existing file without overwriting
File.AppendAllText(filePath, "\nAppended line.");2. Reading from a File
Reading can be done all at once into a string, an array of lines, or an enumerable collection for memory efficiency.
// Read the entire file as a single string
string content = File.ReadAllText(filePath);
// Read all lines into a string array
string[] readLines = File.ReadAllLines(filePath);
// Lazily enumerate lines to handle large files efficiently
foreach (string line in File.ReadLines(filePath))
{
Console.WriteLine(line);
}3. Checking Existence, Copying, Moving, and Deleting
Always check if a file exists before performing destructive operations.
string sourcePath = @"C:\temp\example.txt";
string destinationPath = @"C:\temp\backup.txt";
// Check if file exists
if (File.Exists(sourcePath))
{
// Copy file (true allows overwriting the destination)
File.Copy(sourcePath, destinationPath, overwrite: true);
// Move or rename a file
string movedPath = @"C:\temp\renamed.txt";
File.Move(destinationPath, movedPath);
// Delete a file
File.Delete(movedPath);
}Working with the Directory Class
The static Directory class provides functionality for
creating, moving, querying, and deleting folders and subfolders.
1. Creating and Deleting Directories
Directory.CreateDirectory creates all directories and
subdirectories specified in the path unless they already exist.
string dirPath = @"C:\temp\MyNewFolder";
// Create directory
Directory.CreateDirectory(dirPath);
// Check if directory exists
if (Directory.Exists(dirPath))
{
// Delete directory (set recursive to true to delete contents as well)
Directory.Delete(dirPath, recursive: true);
}2. Listing Files and Subdirectories
You can search within directories using search patterns and control search depth.
string searchDir = @"C:\temp";
// Get all files in a directory
string[] allFiles = Directory.GetFiles(searchDir);
// Get files matching a specific pattern (e.g., text files)
string[] txtFiles = Directory.GetFiles(searchDir, "*.txt");
// Search recursively in all subdirectories
string[] nestedFiles = Directory.GetFiles(searchDir, "*.txt", SearchOption.AllDirectories);
// Get subdirectories
string[] subDirs = Directory.GetDirectories(searchDir);
// Enumerate files lazily for better performance with large directories
foreach (string file in Directory.EnumerateFiles(searchDir, "*.log"))
{
Console.WriteLine(file);
}Combining File and Directory with the Path Class
When working with files and folders, avoid hardcoding directory
separators. Use the Path class alongside File
and Directory to construct reliable file paths:
string folder = @"C:\temp";
string fileName = "report.txt";
// Safely combine paths
string fullPath = Path.Combine(folder, fileName);
// Extract path components
string extension = Path.GetExtension(fullPath); // returns ".txt"
string baseName = Path.GetFileName(fullPath); // returns "report.txt"Exception Handling
File I/O operations involve external resources and are prone to
runtime errors such as missing permissions, non-existent paths, or locks
by other processes. Wrap operations in try-catch
blocks:
try
{
string data = File.ReadAllText(@"C:\temp\data.txt");
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"File not found: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"Access denied: {ex.Message}");
}
catch (IOException ex)
{
Console.WriteLine($"General I/O error: {ex.Message}");
}