← Back to Articles         
C# – File Handling, Streams & I/O Operations

C# – File Handling, Streams & I/O Operations

Published on 12 Oct 2026     7 min read C#
File Handling & I/O

C# – File Handling, Streams & I/O Operations

1. How do you read and write files in C#?

C# provides classes in the System.IO namespace to create, read, write, append, and delete files.

The File class is commonly used for simple file operations.

Example

using System.IO;

// Write to a file
File.WriteAllText("employee.txt", "Hello Syed");

// Read from a file
string content = File.ReadAllText("employee.txt");

Console.WriteLine(content);

// Append text
File.AppendAllText("employee.txt", "\nWelcome");

// Check file existence
bool exists = File.Exists("employee.txt");

Output:

Hello Syed

Explanation

  • WriteAllText() creates or overwrites a file.

  • ReadAllText() reads the complete file content.

  • AppendAllText() adds content without deleting existing data.

  • Exists() checks whether a file exists.

Key Points

  • System.IO provides file-handling classes.

  • File contains static methods.

  • File.ReadAllLines() reads all lines into an array.

  • File.ReadLines() supports lazy, line-by-line reading.

  • Use asynchronous methods for non-blocking I/O.

 

2. What is the difference between File, FileInfo, StreamReader, and StreamWriter?

All four are used for file operations, but their purposes differ.

Comparison

Class

Purpose

Method Type

File

Simple file operations

Static

FileInfo

File operations and metadata

Instance

StreamReader

Read text from a stream

Instance

StreamWriter

Write text to a stream

Instance

Example

using System.IO;

// File
File.WriteAllText("test.txt", "Hello");

// FileInfo
FileInfo info = new FileInfo("test.txt");
Console.WriteLine(info.Length);

// StreamReader
using (StreamReader reader = new StreamReader("test.txt"))
{
    Console.WriteLine(reader.ReadLine());
}

// StreamWriter
using (StreamWriter writer = new StreamWriter("test.txt", append: true))
{
    writer.WriteLine("Welcome");
}

Explanation

  • File is convenient for one-time file operations.

  • FileInfo provides properties such as Length, Name, and CreationTime.

  • StreamReader reads text sequentially.

  • StreamWriter writes text sequentially.

Key Points

  • Use File for simple read/write operations.

  • Use FileInfo when working repeatedly with file metadata.

  • Use StreamReader for sequential text reading.

  • Use StreamWriter for sequential text writing.

  • Dispose readers and writers using using.

 

3. What is the difference between synchronous and asynchronous file operations?

Synchronous file operations block the calling thread until the operation completes.

Asynchronous file operations allow the calling thread to perform other work while waiting for I/O completion.

Example

Synchronous:

string content = File.ReadAllText("employee.txt");

Console.WriteLine(content);

Asynchronous:

string content =
    await File.ReadAllTextAsync("employee.txt");

Console.WriteLine(content);

Flow

Synchronous
-----------
Thread
  |
  +-- Start File Reading
  |
  +-- Wait (Blocked)
  |
  +-- Reading Completed
  |
  +-- Continue Execution


Asynchronous
------------
Thread
  |
  +-- Start File Reading
  |
  +-- Await (Thread Not Blocked)
  |
  +-- I/O Completes
  |
  +-- Resume Execution

Comparison

Synchronous

Asynchronous

Blocks calling thread

Does not block while awaiting I/O

Uses methods like ReadAllText()

Uses methods like ReadAllTextAsync()

Simple execution flow

Uses async/await

Suitable for small console utilities

Useful for scalable Web APIs

Key Points

  • Async I/O improves scalability when threads would otherwise wait.

  • Async does not necessarily create a new thread.

  • Async is not automatically faster for every individual file operation.

  • Prefer async file operations in ASP.NET Core when handling significant I/O.

 

4. What is a Stream in C#?

A Stream represents a sequence of bytes that can be read from or written to a source such as a file, memory, or network connection.

Stream is an abstract class in System.IO.

Common Stream Types

Stream

Purpose

FileStream

Reads/writes file bytes

MemoryStream

Reads/writes bytes in memory

NetworkStream

Transfers bytes over a network

BufferedStream

Adds buffering to another stream

Example

using System.IO;
using System.Text;

using FileStream fs = new FileStream(
    "test.txt",
    FileMode.Create,
    FileAccess.Write
);

byte[] data = Encoding.UTF8.GetBytes("Hello Syed");

fs.Write(data, 0, data.Length);

Explanation

  1. FileStream opens or creates a file.

  2. Encoding.UTF8.GetBytes() converts text into bytes.

  3. Write() writes the bytes to the file.

  4. using automatically disposes the stream.

Flow

C# Application
      |
      v
    Stream
      |
      +-- FileStream    -> Disk
      |
      +-- MemoryStream  -> RAM
      |
      +-- NetworkStream -> Network

Key Points

  • Streams work with bytes.

  • Streams support reading, writing, and sometimes seeking.

  • StreamReader and StreamWriter handle text encoding.

  • Streams implement IDisposable.

  • Streams are commonly used for file uploads and downloads.

 

5. What is the difference between FileStream and MemoryStream?

Both inherit from Stream, but they use different storage locations.

Comparison

FileStream

MemoryStream

Reads/writes files

Reads/writes memory buffers

Uses disk-backed storage

Uses RAM

Requires file access

Does not require a physical file

Useful for large file operations

Useful for temporary in-memory data

Subject to disk I/O

Avoids disk I/O

Example

FileStream:

using FileStream fs = new FileStream(
    "test.txt",
    FileMode.Create
);

byte[] data = { 65, 66, 67 };

fs.Write(data, 0, data.Length);

MemoryStream:

using MemoryStream ms = new MemoryStream();

byte[] data = { 65, 66, 67 };

ms.Write(data, 0, data.Length);

Console.WriteLine(ms.Length);

Output:

3

Explanation

  • FileStream writes bytes to test.txt.

  • MemoryStream stores bytes in memory.

  • Both use the same Write() method because they inherit from Stream.

Key Points

  • FileStream is suitable for disk-based operations.

  • MemoryStream is suitable for temporary data processing.

  • MemoryStream can consume significant RAM for large data.

  • Both support asynchronous operations through the Stream API.

 

6. How do you process large files without loading them entirely into memory?

For large files, use streaming instead of reading the entire file into memory.

Common approaches include StreamReader, File.ReadLines(), and FileStream.

Example

Suppose employees.txt contains one employee name per line.

using System.IO;

using StreamReader reader =
    new StreamReader("employees.txt");

string? line;

while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line);
}

Explanation

  • StreamReader reads one line at a time.

  • The entire file is not loaded into memory.

  • Each line is processed before reading the next.

  • Memory consumption stays relatively low, assuming individual lines are reasonably sized.

Flow

Large File (2 GB)
       |
       v
   StreamReader
       |
       +-- Read Line 1 -> Process
       |
       +-- Read Line 2 -> Process
       |
       +-- Read Line 3 -> Process
       |
       +-- Continue Until EOF

Alternative

foreach (string line in File.ReadLines("employees.txt"))
{
    Console.WriteLine(line);
}

File.ReadLines() lazily reads lines instead of loading all lines at once.

Key Points

  • Avoid ReadAllText() for very large files.

  • Use StreamReader for sequential text processing.

  • Use File.ReadLines() for simpler line-by-line processing.

  • Use FileStream with fixed-size buffers for large binary files.

  • In Web APIs, stream large uploads and downloads where practical.

 

7. How do you handle file access exceptions and resource disposal?

File operations may fail because of missing files, permission issues, locked files, or disk errors.

Use try-catch to handle exceptions and using to release resources.

Example

using System;
using System.IO;

try
{
    using StreamReader reader =
        new StreamReader("employee.txt");

    string content = reader.ReadToEnd();

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

Explanation

  1. The try block performs file reading.

  2. FileNotFoundException handles missing files.

  3. UnauthorizedAccessException handles permission problems.

  4. IOException handles other I/O failures.

  5. using ensures the reader is disposed even if an exception occurs.

Resource Disposal Flow

Open File
    |
    v
Read / Write
    |
    +-- Success ------+
    |                 |
    +-- Exception ----+
                      |
                      v
                Dispose()
                      |
                      v
              Release Resources

Common File Exceptions

Exception

Reason

FileNotFoundException

File does not exist

DirectoryNotFoundException

Directory does not exist

UnauthorizedAccessException

Insufficient permissions

IOException

I/O failure or sharing conflict

PathTooLongException

File path exceeds supported limits

Key Points

  • Use try-catch for expected file access failures.

  • Catch specific exceptions before general exceptions.

  • Use using for automatic resource disposal.

  • Use await using when asynchronous disposal is appropriate.

  • Avoid leaving files or streams open unnecessarily.

  • Log exceptions in production applications.

 

Quick Interview Revision

Question

Important Answer

File Handling

Use System.IO classes to read and write files

File vs FileInfo

Static methods vs instance methods and metadata

StreamReader vs StreamWriter

Read text vs write text

Sync vs Async

Blocking vs non-blocking I/O

Stream

Abstraction for reading/writing bytes

FileStream vs MemoryStream

Disk-backed vs memory-backed storage

Large File Processing

Read line-by-line or in fixed-size chunks

Exception Handling

Use specific catch blocks

Resource Disposal

Use using or await using

Interview Tip for .NET Tech Lead: Be prepared to explain how you would handle a 2 GB CSV file upload in ASP.NET Core Web API. A strong answer should mention streaming, buffered processing, asynchronous I/O, validation, resource disposal, and avoiding unnecessary memory allocation.

← Back to Articles