Paramclasses Academy - Blog

Tutorials Details

←
Post 25 of 30
→

What is File Handling in C#: Read and Write Text and CSV Files ?

What is File Handling in C#: Read and Write Text and CSV Files ?

October 26, 2026

Introduction

File handling is an essential part of C# programming. It allows applications to store information permanently, read previously saved data, update files, and exchange information with other systems.

For example, a student management system may save student records in a text file, while an inventory application may export product details to a CSV file. File handling makes these operations possible without requiring a database for every simple storage task.

C# provides several classes in the System.IO namespace for working with files and directories. Commonly used classes include File, FileInfo, StreamReader, StreamWriter, and Directory.

In this tutorial, you will learn how to create, read, write, append, and manage text files, work with CSV data, handle file-related exceptions, and follow best practices for reliable file operations.

1. What Is File Handling in C#?

File handling is the process of creating, reading, writing, updating, and managing files through a program.

Files can store many types of information, including:

  • Plain text and application logs

  • Student and employee records

  • Product and inventory data

  • Configuration settings

  • CSV data exported from spreadsheets

  • Reports and other application-generated information

C# provides APIs that make these operations straightforward.

What Is the System.IO Namespace?

The System.IO namespace contains types for working with files, directories, streams, and paths.

Start by importing it:

using System.IO;

For many of the examples in this tutorial, you will also need:

using System;

In modern .NET projects, some namespaces may already be available through implicit or global usings.

2. Important Classes for File Handling

Class Purpose
File Provides static methods for common file operations
FileInfo Provides instance-based information and operations for a specific file
StreamReader Reads text from a stream
StreamWriter Writes text to a stream
Directory Provides static methods for working with directories
DirectoryInfo Provides instance-based directory operations
Path Helps build and inspect file paths

For beginners, the File class is usually the easiest place to start.

3. Creating and Writing a Text File

The File.WriteAllText() method creates a file if it does not exist and writes the supplied text to it. If the file already exists, its previous contents are overwritten.

Example: Create a Text File

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "message.txt";
        string content = "Welcome to C# File Handling!";

        File.WriteAllText(filePath, content);

        Console.WriteLine("File created and written successfully.");
    }
}

Output:

File created and written successfully.

The program creates message.txt in the application's current working directory, assuming it has permission to write there.

Understanding the Code

  1. filePath specifies the target file.

  2. content stores the text to write.

  3. File.WriteAllText() writes the content to the file.

  4. The console message confirms that the method returned successfully.

Important: A relative path such as message.txt is resolved against the application's current working directory, which may not be the same as the source-code folder.

4. Reading a Text File

The File.ReadAllText() method reads the complete contents of a text file into a string.

Example: Read a Text File

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "message.txt";

        if (File.Exists(filePath))
        {
            string content = File.ReadAllText(filePath);

            Console.WriteLine("File Content:");
            Console.WriteLine(content);
        }
        else
        {
            Console.WriteLine("File not found.");
        }
    }
}

Example output:

File Content:
Welcome to C# File Handling!

Why Use File.Exists()?

File.Exists() can help determine whether a file is present before attempting to read it. However, file-system state can change between checking and opening a file, so the actual operation should still be handled appropriately.

For large files, reading everything into memory may be inefficient. In such cases, consider reading line by line with StreamReader or using another streaming approach.

5. Appending Text to an Existing File

Sometimes you want to add new information without deleting the existing content. For this purpose, C# provides File.AppendAllText().

Example: Append Text

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "message.txt";

        File.AppendAllText(
            filePath,
            Environment.NewLine + "This is a new line."
        );

        Console.WriteLine("Text appended successfully.");
    }
}

If message.txt already contains the welcome message, the file will contain both lines after this operation.

Important: File.AppendAllText() creates the file if it does not exist. If your program needs to append frequently or process a stream of data, a StreamWriter opened in append mode may be more suitable.

6. Writing Multiple Lines to a File

The File.WriteAllLines() method writes a collection of strings to a file, placing each string on a separate line.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string[] lines =
        {
            "Name: Amit",
            "Course: C#",
            "Status: Active"
        };

        File.WriteAllLines("student.txt", lines);

        Console.WriteLine("Student information saved.");
    }
}

File content:

Name: Amit
Course: C#
Status: Active

You can read those lines using File.ReadAllLines():

string[] lines = File.ReadAllLines("student.txt");

foreach (string line in lines)
{
    Console.WriteLine(line);
}

These methods are convenient for small and medium-sized text files. For very large files, consider streaming to reduce memory usage.

7. Using StreamWriter to Write Text

StreamWriter allows you to write text progressively rather than preparing the entire file content as one string.

Example: Write Multiple Lines

using System;
using System.IO;

class Program
{
    static void Main()
    {
        using (StreamWriter writer =
               new StreamWriter("students.txt"))
        {
            writer.WriteLine("Amit");
            writer.WriteLine("Priya");
            writer.WriteLine("Rahul");
        }

        Console.WriteLine("Student names saved.");
    }
}

The using statement ensures that the writer is disposed of when the block ends, flushing buffered data and releasing the file handle.

By default, opening StreamWriter this way overwrites an existing file. To append instead, use:

using (StreamWriter writer =
       new StreamWriter("students.txt", append: true))
{
    writer.WriteLine("Neha");
}

The append: true argument instructs the writer to add content at the end of the file.

8. Reading a File with StreamReader

StreamReader is useful when you want to process a text file line by line.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        using (StreamReader reader =
               new StreamReader("students.txt"))
        {
            string? line;

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

Example output:

Amit
Priya
Rahul

The ReadLine() method returns the next line or null when the end of the stream is reached. The nullable string annotation is suitable for projects using nullable reference types.

Line-by-line reading is often preferable for large files because it avoids loading the entire file into memory at once.

9. File Handling with the File Class

The File class provides convenient methods for common operations.

Method Purpose
File.Create() Creates or overwrites a file and returns a stream
File.WriteAllText() Writes text to a file
File.ReadAllText() Reads all text into a string
File.WriteAllLines() Writes multiple lines
File.ReadAllLines() Reads all lines into an array
File.AppendAllText() Appends text to a file
File.Copy() Copies a file
File.Move() Moves or renames a file
File.Delete() Deletes a file
File.Exists() Checks whether a file exists

Example: Copy a File

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string source = "students.txt";
        string destination = "students_backup.txt";

        if (File.Exists(source))
        {
            File.Copy(source, destination, overwrite: true);

            Console.WriteLine("File copied successfully.");
        }
        else
        {
            Console.WriteLine("Source file not found.");
        }
    }
}

The overwrite: true argument allows the destination file to be replaced if it already exists.

Example: Rename or Move a File

File.Move("students.txt", "student_records.txt");

This operation moves the file to the destination path. If the paths are in the same directory, it effectively renames the file. Destination-exists behavior depends on the overload used; the simple overload shown here does not overwrite an existing destination file.

Example: Delete a File

if (File.Exists("student_records.txt"))
{
    File.Delete("student_records.txt");
}

Deleting a file is a destructive operation. Always verify the intended path before performing deletion in a real application.

10. Working with File Paths

Hardcoding paths can make an application difficult to move between computers or operating systems. The Path class helps build paths correctly.

Example: Combine Directory and File Name

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string folder = "Data";
        string fileName = "students.txt";

        string fullPath = Path.Combine(folder, fileName);

        Console.WriteLine(fullPath);
    }
}

The resulting path uses the appropriate directory separator for the current platform.

Example: Get the Extension and File Name

string path = @"C:\Reports\students.csv";

Console.WriteLine(Path.GetFileName(path));
Console.WriteLine(Path.GetExtension(path));
Console.WriteLine(Path.GetFileNameWithoutExtension(path));

Output:

students.csv
.csv
students

These examples use a Windows-style path string. Path interprets path syntax according to the platform on which the application runs, so use paths appropriate to your environment.

11. Creating and Managing Directories

Before saving files, you may need to create a directory.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string folderPath = Path.Combine(
            Environment.CurrentDirectory,
            "Data"
        );

        Directory.CreateDirectory(folderPath);

        string filePath = Path.Combine(
            folderPath,
            "report.txt"
        );

        File.WriteAllText(filePath, "Monthly report");

        Console.WriteLine("Report saved successfully.");
    }
}

Directory.CreateDirectory() creates the specified directory and any missing parent directories. It does not fail merely because the directory already exists.

Use Path.Combine() rather than manually joining path segments with slash characters.

12. What Is a CSV File?

CSV stands for Comma-Separated Values. It is a text format commonly used to exchange tabular data between spreadsheets, databases, and applications.

For example:

Name,Age,Course
Amit,21,C#
Priya,22,Java
Rahul,20,Python

Each line represents a record, while commas separate fields in a simple CSV file.

CSV is widely used for:

  • Exporting reports

  • Importing spreadsheet data

  • Transferring records between systems

  • Storing simple tabular data

  • Processing product, customer, or student lists

Important: Real CSV files can contain quoted fields, commas inside values, line breaks inside quoted fields, and escaped quotation marks. Splitting every line on commas is not a complete CSV parser.

13. Writing CSV Data in C#

For a simple CSV file whose values do not contain commas, quotes, or line breaks, you can write rows directly.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string[] lines =
        {
            "Name,Age,Course",
            "Amit,21,C#",
            "Priya,22,Java",
            "Rahul,20,Python"
        };

        File.WriteAllLines("students.csv", lines);

        Console.WriteLine("CSV file created successfully.");
    }
}

This creates a CSV file with a header row and three student records.

For arbitrary user-entered data, however, fields must be escaped correctly. Consider the following value:

Amit, Sharma

If it is written without quotes, the comma may be interpreted as a separator rather than part of the name.

Escaping CSV Fields

A common CSV rule is to enclose fields containing commas, quotation marks, or line breaks in double quotes. Any double quote inside a quoted field is doubled.

For example, the value:

Amit "Developer" Sharma

should be represented as:

"Amit ""Developer"" Sharma"

For production applications, use a reliable CSV library rather than implementing every CSV edge case yourself.

14. Reading a Simple CSV File

If you know that a CSV file contains simple values without quoted commas or embedded line breaks, you can use a basic approach.

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "students.csv";

        if (!File.Exists(filePath))
        {
            Console.WriteLine("CSV file not found.");
            return;
        }

        string[] lines = File.ReadAllLines(filePath);

        foreach (string line in lines.Skip(1))
        {
            string[] fields = line.Split(',');

            if (fields.Length == 3)
            {
                string name = fields[0];
                string age = fields[1];
                string course = fields[2];

                Console.WriteLine(
                    $"{name} | {age} | {course}");
            }
            else
            {
                Console.WriteLine("Invalid CSV row.");
            }
        }
    }
}

Add this namespace to the imports:

using System.Linq;

Example output:

Amit | 21 | C#
Priya | 22 | Java
Rahul | 20 | Python

The example skips the header row with Skip(1) and checks the expected number of fields.

Limitation: Split(',') does not correctly parse general CSV files containing quoted commas or embedded line breaks. Use a CSV parser for files that may contain such data.

15. Reading and Writing CSV Files with a CSV Library

For production-quality CSV processing, a dedicated parser is safer than splitting lines manually.

One commonly used .NET library is CsvHelper. Install the package using the NuGet Package Manager or the .NET CLI:

dotnet add package CsvHelper

The following example illustrates how to write and read structured records. It assumes a compatible version of CsvHelper is installed.

using System;
using System.Globalization;
using System.IO;
using CsvHelper;

public class Student
{
    public string Name { get; set; } = "";
    public int Age { get; set; }
    public string Course { get; set; } = "";
}

class Program
{
    static void Main()
    {
        string filePath = "students.csv";

        Student[] students =
        {
            new Student
            {
                Name = "Amit, Sharma",
                Age = 21,
                Course = "C#"
            },
            new Student
            {
                Name = "Priya",
                Age = 22,
                Course = "Java"
            }
        };

        using (var writer = new StreamWriter(filePath))
        using (var csv = new CsvWriter(
            writer,
            CultureInfo.InvariantCulture))
        {
            csv.WriteRecords(students);
        }

        using (var reader = new StreamReader(filePath))
        using (var csv = new CsvReader(
            reader,
            CultureInfo.InvariantCulture))
        {
            var records = csv.GetRecords<Student>();

            foreach (Student student in records)
            {
                Console.WriteLine(
                    $"{student.Name} | {student.Age} | {student.Course}");
            }
        }
    }
}

The CSV library handles quoting and escaping rules that a simple Split(',') implementation cannot reliably support.

When working with external files, also validate input values and handle malformed records or conversion errors according to your application's requirements.

16. Handling File Exceptions

File operations can fail for several reasons:

  • The file does not exist.

  • The application lacks the required permissions.

  • The path is invalid.

  • Another process prevents access.

  • The disk or storage device has an issue.

  • The file contains unexpected data.

C# uses exceptions to report many file-system errors.

Example: Handle File-Related Errors

using System;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "message.txt";

        try
        {
            string content = File.ReadAllText(filePath);

            Console.WriteLine(content);
        }
        catch (FileNotFoundException)
        {
            Console.WriteLine("The specified file was not found.");
        }
        catch (UnauthorizedAccessException)
        {
            Console.WriteLine("Access to the file was denied.");
        }
        catch (IOException ex)
        {
            Console.WriteLine($"File operation failed: {ex.Message}");
        }
    }
}

This example handles common file-related errors explicitly.

A DirectoryNotFoundException is an IOException subtype, so it is covered by the final IOException handler here. Add a more specific handler before it if you need different behavior for missing directories.

Avoid catching every exception without a clear recovery strategy. Handle the failures your application can reasonably address, and log useful diagnostic information where appropriate.

17. Asynchronous File Handling

For applications that perform file operations without blocking a user interface or request-processing thread, asynchronous APIs can be useful.

For example, File.ReadAllTextAsync() reads a text file asynchronously.

using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        string filePath = "message.txt";

        try
        {
            string content =
                await File.ReadAllTextAsync(filePath);

            Console.WriteLine(content);
        }
        catch (IOException ex)
        {
            Console.WriteLine(
                $"Unable to read the file: {ex.Message}");
        }
    }
}

This example requires a modern .NET version that supports File.ReadAllTextAsync() and asynchronous Main.

Asynchronous file operations can improve responsiveness, but they do not automatically make every operation faster. For small, simple console programs, synchronous methods may be perfectly adequate.

18. File Handling Best Practices

Follow these practices when working with files in C#:

  1. Use Path.Combine(): Build paths safely instead of joining path segments manually.

  2. Dispose streams correctly: Use using statements or declarations with readers and writers.

  3. Handle expected exceptions: Consider missing files, access restrictions, invalid paths, and I/O failures.

  4. Avoid loading huge files into memory: Use streaming approaches when appropriate.

  5. Choose the correct write operation: Remember that WriteAllText() overwrites existing content, while AppendAllText() adds content.

  6. Validate external data: Treat file contents as input that may be incomplete or malformed.

  7. Use a CSV library when necessary: Do not rely on comma splitting for general CSV data.

  8. Use explicit encoding when required: Coordinate text encoding with the systems that will read the file.

  9. Protect sensitive information: Apply suitable access permissions and avoid storing secrets in plain text.

  10. Be careful with destructive operations: Confirm the intended path before moving or deleting files.

19. Practice Exercises

Practice the following tasks to improve your file-handling skills.

Exercise 1: Create a File

Create a file named welcome.txt and write a welcome message to it.

Exercise 2: Read a File

Read welcome.txt and display its content in the console.

Exercise 3: Append Text

Add a new line to an existing file without removing its previous content.

Exercise 4: Save Student Records

Store the names of five students in a text file, with one student per line.

Exercise 5: Copy a File

Copy a file to a backup file and handle the case where the source does not exist.

Exercise 6: Create a CSV File

Create a CSV file containing student names, ages, and courses.

Exercise 7: Read CSV Data

Read a simple CSV file, skip the header row, and display each record.

Exercise 8: Handle File Exceptions

Modify a file-reading program to handle missing files and access-denied errors.

Exercise 9: Create a Directory

Create a Data directory and save a report file inside it using Path.Combine().

Exercise 10: Use Asynchronous Reading

Use File.ReadAllTextAsync() to read a text file in an asynchronous method.

20. Quick Knowledge Check

1. Which namespace contains common C# file-handling types?

A. System.Web
B. System.IO
C. System.Net
D. System.Linq

Correct answer: B

2. Which method reads the entire contents of a text file into a string?

A. File.WriteAllText()
B. File.Delete()
C. File.ReadAllText()
D. File.Copy()

Correct answer: C

3. Which method appends text to a file?

A. File.AppendAllText()
B. File.ReadAllLines()
C. File.Exists()
D. File.Move()

Correct answer: A

4. Which class is useful for reading text one line at a time?

A. StreamWriter
B. StreamReader
C. DirectoryInfo
D. Path

Correct answer: B

5. Why should you use a dedicated CSV parser for complex CSV data?

A. It automatically creates databases
B. It replaces C# syntax
C. It correctly handles quoting and escaped values
D. It prevents every possible file error

Correct answer: C

6. What does Path.Combine() help you do?

A. Combine file path segments
B. Delete multiple files
C. Read CSV headers
D. Sort a list

Correct answer: A

21. Frequently Asked Questions (FAQs)

What is file handling in C#?

File handling is the process of creating, reading, writing, appending, moving, copying, and deleting files through a C# application.

Which namespace is used for file handling in C#?

The System.IO namespace contains common file, directory, path, and stream types.

What is the difference between WriteAllText() and AppendAllText()?

File.WriteAllText() replaces the existing file contents, whereas File.AppendAllText() adds text at the end of the file. Both methods create the file if it does not exist.

What is the difference between StreamReader and StreamWriter?

StreamReader reads text from a stream, while StreamWriter writes text to a stream.

What is a CSV file?

A CSV file is a text-based format for representing tabular data using delimiters, commonly commas. CSV fields may require quotation and escaping when they contain special characters.

Can C# read and write Excel files using basic file-handling methods?

Basic file methods can read and write text, but Excel workbook formats such as .xlsx require a suitable library or another specialized approach. A CSV file can be opened by spreadsheet applications, but it is not the same as an Excel workbook.

Why is exception handling important in file operations?

File operations depend on the file system, permissions, available storage, and the presence of the requested file. Exception handling allows an application to respond appropriately when these operations fail.

Is asynchronous file handling always better?

No. Asynchronous methods are useful when responsiveness or scalable I/O matters, but synchronous methods may be simpler and sufficient for small operations.

Conclusion

File handling is an important C# skill because applications often need to save, retrieve, and exchange data. By learning the File, StreamReader, StreamWriter, Directory, and Path APIs, you can build programs that manage text files and directories reliably.

You can also use CSV files to exchange structured records with spreadsheet applications and other systems. For complex CSV data, a dedicated parser provides more reliable handling than splitting each line on commas.

Practice creating files, reading their contents, appending information, handling exceptions, and processing CSV records. These skills will prepare you for more advanced .NET development tasks.

←
Post 25 of 30
→