Skip to content

File I/O in C# — Complete Guide

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about File I/O in C#. We cover key concepts, practical examples, and best practices to help you master this topic.

Hook

Every real-world application needs to persist data. Whether you are saving user preferences, processing log files, or importing data from an external source, file I/O is an essential skill. C# provides a rich set of classes in the System.IO namespace to handle files and directories with ease.

Learning Path

graph LR
  A[File I/O Basics] --> B[StreamReader StreamWriter]
  B --> C[File Directory Path]
  C --> D[Async I/O]
  D --> E[Binary Serialization]
  style A fill:#4a90d9,color:#fff
  style B fill:#4a90d9,color:#fff
  style C fill:#4a90d9,color:#fff
  style D fill:#4a90d9,color:#fff
  style E fill:#4a90d9,color:#fff

The File Class

The File class provides static methods for creating, copying, deleting, and moving files. It is the simplest way to perform basic file operations.

string path = "example.txt";

// Write all text (creates or overwrites)
File.WriteAllText(path, "Hello, C# File I/O!");

// Read all text
string content = File.ReadAllText(path);
Console.WriteLine(content);

// Append text
File.AppendAllText(path, "\nAppended line.");

// Check existence
bool exists = File.Exists(path);
Console.WriteLine($"File exists: {exists}");

// Delete
File.Delete(path);

Output:

Hello, C# File I/O!
File exists: True

StreamReader and StreamWriter

For more control, use StreamReader and StreamWriter. These classes read and write text line by line.

string path = "lines.txt";

// Writing lines
using (StreamWriter writer = new StreamWriter(path))
{
    writer.WriteLine("First line");
    writer.WriteLine("Second line");
    writer.WriteLine("Third line");
}

// Reading lines
using (StreamReader reader = new StreamReader(path))
{
    string? line;
    while ((line = reader.ReadLine()) != null)
    {
        Console.WriteLine(line);
    }
}

Output:

First line
Second line
Third line

The using statement ensures the file handle is closed even if an exception occurs.

The Directory Class

Directory provides static methods for creating, deleting, and enumerating directories.

string dir = "MyFolder";

// Create directory
Directory.CreateDirectory(dir);

// Create a file inside
File.WriteAllText(Path.Combine(dir, "note.txt"), "Hello!");

// List files
string[] files = Directory.GetFiles(dir);
foreach (string file in files)
{
    Console.WriteLine(Path.GetFileName(file));
}

// Delete directory recursively
Directory.Delete(dir, recursive: true);

Output:

note.txt

The Path Class

Path helps you manipulate file and directory paths safely across platforms.

string fullPath = Path.Combine("folder", "sub", "file.txt");
Console.WriteLine($"Combined: {fullPath}");

string ext = Path.GetExtension("document.pdf");
Console.WriteLine($"Extension: {ext}");

string name = Path.GetFileNameWithoutExtension("document.pdf");
Console.WriteLine($"Name: {name}");

string? dir = Path.GetDirectoryName("/home/user/file.txt");
Console.WriteLine($"Directory: {dir}");

string temp = Path.GetTempFileName();
Console.WriteLine($"Temp file: {temp}");

Output:

Combined: folder/sub/file.txt
Extension: .pdf
Name: document
Directory: /home/user/file.txt
Temp file: /tmp/tmpXXXXXX.tmp

Async File I/O

Modern C# applications should use async methods to avoid blocking threads during I/O operations.

async Task ReadFileAsync(string path)
{
    using (StreamReader reader = new StreamReader(path))
    {
        string content = await reader.ReadToEndAsync();
        Console.WriteLine(content);
    }
}

async Task WriteFileAsync(string path, string content)
{
    await File.WriteAllTextAsync(path, content);
    Console.WriteLine("File written asynchronously.");
}

The async variants are available in .NET Core and .NET 5+ for all major File and stream methods.

Binary Files with BinaryReader and BinaryWriter

For non-text data, use BinaryWriter and BinaryReader.

string path = "data.bin";

using (BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
{
    writer.Write(42);              // int
    writer.Write(3.14);            // double
    writer.Write("Hello binary");   // string
}

using (BinaryReader reader = new BinaryReader(File.Open(path, FileMode.Open)))
{
    int i = reader.ReadInt32();
    double d = reader.ReadDouble();
    string s = reader.ReadString();
    Console.WriteLine($"{i}, {d}, {s}");
}

Output:

42, 3.14, Hello binary

File Security and Exceptions

Always handle exceptions when working with the file system.

try
{
    string content = File.ReadAllText("nonexistent.txt");
}
catch (FileNotFoundException)
{
    Console.WriteLine("File not found.");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("Access denied.");
}
catch (IOException ex)
{
    Console.WriteLine($"I/O error: {ex.Message}");
}

Common Mistakes

  1. Forgetting to dispose streams: Always wrap streams in using statements or call Dispose.

  2. Using relative paths without checking the working directory: Use Path.GetFullPath or AppContext.BaseDirectory to resolve paths.

  3. Ignoring encoding: Default encoding is UTF-8. Use Encoding.UTF8 explicitly when working with non-standard text.

  4. Blocking the UI thread with synchronous I/O: Always use async methods in GUI or web applications to avoid freezing.

  5. Assuming files are closed immediately: Streams buffer writes; call Flush() or ensure disposal to persist data.

Practice Questions

  1. Write a method that reads a text file, counts the number of words, and returns the count.

  2. Create a program that copies all .txt files from one directory to another using Directory.EnumerateFiles.

  3. Implement a simple logger that appends timestamped messages to a log file using StreamWriter.

  4. Challenge: Write a program that recursively lists all files in a directory tree with their sizes in a human-readable format.

FAQ

What is the difference between File.ReadAllText and StreamReader?

File.ReadAllText reads the entire file into memory at once. StreamReader reads line-by-line or character-by-character, which is better for large files.

Should I use using or try/finally for streams?

The using statement is syntactic sugar for try/finally with Dispose. It is the recommended approach for most cases.

How do I handle file path cross-platform differences?

Use Path.Combine and Path.DirectorySeparatorChar instead of hardcoding slashes. .NET handles differences on Windows, Linux, and macOS.

Can I read and write to the same file simultaneously?

Yes, use FileStream with FileAccess.ReadWrite. However, be careful about locking and position management.

What is the maximum file size File.ReadAllText can handle?

It depends on available memory. For files over a few hundred MB, use streaming (StreamReader) instead of loading the entire file.

Mini Project: File Sorter

Create a console application that reads a text file containing one number per line, sorts them, and writes the sorted numbers to a new file. Include error handling for invalid lines and empty files.

using System;

string inputPath = "input.txt";
string outputPath = "sorted_output.txt";

// Generate sample data
File.WriteAllLines(inputPath, new[] { "42", "7", "19", "3", "88", "12" });

try
{
    var numbers = new List<int>();
    string[] lines = File.ReadAllLines(inputPath);

    foreach (string line in lines)
    {
        if (int.TryParse(line.Trim(), out int num))
            numbers.Add(num);
        else
            Console.WriteLine($"Skipping invalid line: {line}");
    }

    numbers.Sort();
    File.WriteAllLines(outputPath, numbers.Select(n => n.ToString()));

    Console.WriteLine($"Sorted {numbers.Count} numbers to {outputPath}");
    Console.WriteLine(string.Join(", ", numbers));
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

Output:

Sorted 6 numbers to sorted_output.txt
3, 7, 12, 19, 42, 88

This project combines file reading, Parsing, sorting, and writing -- all core file I/O skills for your C# toolkit. The .NET base class library makes these operations straightforward and reliable.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro