Text File Reading
Vaibhav • September 10, 2025
Reading text files is one of the most common tasks in software development. Whether you're importing configuration settings, processing logs, or analyzing user-generated content, understanding how to read text files efficiently and safely is essential. In this article, we’ll explore the different ways to read text files in C#, how to handle large files, and how to avoid common pitfalls - all while staying within the scope of what we've covered so far in the curriculum.
Reading a Whole File at Once
The simplest way to read a text file is to use File.ReadAllText
. This method
reads the entire contents of a file into a single string.
string content = File.ReadAllText("notes.txt");
Console.WriteLine(content);
This is ideal for small files where you want to process or display the entire content at once. The method automatically opens, reads, and closes the file, so you don’t need to manage resources manually.
ReadAllText
loads the entire file into memory. For
large files, this can cause performance issues or even out-of-memory errors.
Reading Line by Line
For larger files or when you want to process each line individually, use File.ReadLines
or File.ReadAllLines
. These
methods return an enumerable collection of strings - one for each line.
foreach (string line in File.ReadLines("log.txt"))
{
Console.WriteLine(line);
}
ReadLines
is more memory-efficient than ReadAllLines
because it uses lazy evaluation - it reads lines one at a time as
you iterate. This is especially useful for processing logs, CSVs, or any file where you don’t need the entire
content at once.
Prefer ReadLines
over ReadAllLines
for
large files. It reduces memory usage and improves
performance.
Using StreamReader for More Control
If you need more control over how the file is read - such as reading character-by-character, skipping lines, or
handling encoding - use StreamReader
. This class gives you fine-grained access
to the file stream.
using StreamReader reader = new StreamReader("data.txt");
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
Console.WriteLine(line);
}
This approach is useful when you need to process the file in a custom way. StreamReader
also allows you to specify the encoding, which is important when
working with non-ASCII text.
StreamReader
implements IDisposable
, so it
should be used with a using
statement to ensure the file is closed
properly.
Reading with Encoding
By default, StreamReader
uses UTF-8 encoding. If your file uses a different
encoding (e.g., UTF-16, ISO-8859-1), you can specify it explicitly:
using StreamReader reader = new StreamReader("legacy.txt", Encoding.GetEncoding("ISO-8859-1"));
string content = reader.ReadToEnd();
Console.WriteLine(content);
This ensures that special characters are interpreted correctly. Misinterpreting encoding can lead to corrupted or unreadable text.
You can detect a file’s encoding using StreamReader.CurrentEncoding
after
reading the first few bytes.
Handling File Not Found and Access Errors
File reading can fail for many reasons - the file might not exist, you might not have permission, or the file
might be locked by another process. Always wrap file operations in a try-catch
block:
try
{
string content = File.ReadAllText("missing.txt");
}
catch (FileNotFoundException)
{
Console.WriteLine("File not found.");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Access denied.");
}
This makes your application more robust and user-friendly. Instead of crashing, it can show a helpful message or take corrective action.
Reading Partial Content
Sometimes you only need part of a file - the first few lines, or a specific section. You can use StreamReader
to read selectively:
using StreamReader reader = new StreamReader("data.txt");
for (int i = 0; i < 5; i++)
{
string line = reader.ReadLine();
Console.WriteLine(line);
}
This reads only the first five lines. You can also skip lines or search for specific markers in the file.
Reading Character by Character
For advanced scenarios like parsing custom formats or building a lexer, you might need to read one character at a time:
using StreamReader reader = new StreamReader("input.txt");
int ch;
while ((ch = reader.Read()) != -1)
{
Console.Write((char)ch);
}
This reads the file character-by-character until the end. It’s slower than line-based reading but gives you full control over parsing.
Skipping Blank Lines and Comments
When processing configuration files or scripts, you may want to skip empty lines or lines that start with a comment symbol:
foreach (string line in File.ReadLines("config.txt"))
{
if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#"))
continue;
Console.WriteLine($"Processing: {line}");
}
This pattern is common in parsers and preprocessors. It ensures that only meaningful lines are processed.
Reading Structured Text (Preview)
While this article focuses on plain text, many files use structured formats like CSV, JSON, or XML. You can still read them as text, but parsing them requires additional logic. For example, reading a CSV file line-by-line:
foreach (string line in File.ReadLines("data.csv"))
{
string[] fields = line.Split(',');
Console.WriteLine($"Name: {fields[0]}, Age: {fields[1]}");
}
This splits each line into fields using a comma delimiter. We’ll cover CSV processing in detail in a later article.
Performance Considerations
Reading files is generally fast, but performance can degrade with large files or inefficient patterns. Here are a few tips:
- Use
ReadLines
for large files to avoid loading everything into memory. - Avoid repeated
ReadAllText
calls - cache the content if needed. - Use buffered reading (
StreamReader
) for custom parsing.
Profile your file reading logic if performance matters. Use Stopwatch
to
measure read times and optimize accordingly.
Summary
Reading text files in C# is straightforward but powerful. You’ve learned how to read entire files, process them
line-by-line, use StreamReader
for advanced control, handle encoding, and
manage errors gracefully. These skills are foundational for many real-world applications - from log analysis to
configuration loading. In the next article, we’ll explore how to write text files, including appending,
overwriting, and formatting output for readability and structure.