C# StreamReader
last modified April 20, 2025
This tutorial explains how to use the StreamReader class in C# to read text data from files. StreamReader provides methods for reading character data from streams with various encodings.
The StreamReader class reads characters from a byte stream in a specific encoding. It inherits from TextReader and is designed for reading text files efficiently.
StreamReader
automatically handles different text encodings
like UTF-8, Unicode, and ASCII. It provides methods for reading lines,
entire files, or character-by-character processing.
Basic StreamReader Example
This example demonstrates reading a text file line by line using StreamReader. It shows the simplest way to process a text file.
using System; using System.IO; class Program { static void Main() { string filePath = "example.txt"; // Create a sample file first File.WriteAllText(filePath, "First line\nSecond line\nThird line"); // Read the file line by line using (StreamReader reader = new StreamReader(filePath)) { string line; int lineNumber = 1; while ((line = reader.ReadLine()) != null) { Console.WriteLine($"Line {lineNumber}: {line}"); lineNumber++; } } } }
The program first creates a sample text file with three lines. Then it
uses StreamReader
to read the file line by line. The
ReadLine
method returns null when the end of file is
reached.
The using
statement ensures proper resource cleanup. Each
line is printed with its line number. This pattern is common for text
file processing in C#.
Reading Entire File at Once
StreamReader can read an entire file in one operation using
ReadToEnd
. This is useful for small files that can fit in
memory.
using System; using System.IO; class Program { static void Main() { string filePath = "document.txt"; // Create sample file File.WriteAllText(filePath, "This is the entire content\nof the text file."); // Read entire file using (StreamReader reader = new StreamReader(filePath)) { string content = reader.ReadToEnd(); Console.WriteLine("File content:"); Console.WriteLine(content); Console.WriteLine($"\nTotal characters: {content.Length}"); } } }
ReadToEnd
reads all characters from the current position
to the end of the stream. It returns a single string containing the
entire file content.
This approach is simple but should be used with caution for large files. For big files, line-by-line reading is more memory efficient.
Reading Character by Character
StreamReader provides Read
method for reading individual
characters. This example shows how to process a file character by
character.
using System; using System.IO; class Program { static void Main() { string filePath = "chars.txt"; File.WriteAllText(filePath, "ABC\n123"); using (StreamReader reader = new StreamReader(filePath)) { int ch; int count = 0; while ((ch = reader.Read()) != -1) { count++; Console.WriteLine($"Char {count}: {(char)ch} (Unicode: {ch})"); } Console.WriteLine($"\nTotal characters read: {count}"); } } }
The Read
method returns the next character as an integer,
or -1 at end of file. We cast the integer to char for display.
This approach is useful for low-level text processing where you need to examine each character individually. Note it includes newline characters.
Specifying File Encoding
StreamReader can handle different text encodings. This example shows how to read files with specific encodings like UTF-8 and Unicode.
using System; using System.IO; using System.Text; class Program { static void Main() { string filePath = "unicode.txt"; // Create file with Unicode encoding File.WriteAllText(filePath, "Привет мир!", Encoding.Unicode); // Read with explicit encoding using (StreamReader reader = new StreamReader(filePath, Encoding.Unicode)) { string content = reader.ReadToEnd(); Console.WriteLine("Read content: " + content); Console.WriteLine("\nFirst character: " + content[0]); Console.WriteLine("Encoding: " + reader.CurrentEncoding.EncodingName); } } }
The example writes text using Unicode encoding and reads it back with
the same encoding. CurrentEncoding
shows the encoding
being used.
Always specify the correct encoding when reading non-ASCII text files. The default encoding is UTF-8, but many legacy systems use other encodings.
Peeking at Next Character
StreamReader's Peek
method allows looking at the next
character without consuming it. This is useful for parsing scenarios.
using System; using System.IO; class Program { static void Main() { string filePath = "data.txt"; File.WriteAllText(filePath, "ABC\n123"); using (StreamReader reader = new StreamReader(filePath)) { Console.WriteLine("Peek first: " + (char)reader.Peek()); Console.WriteLine("Read first: " + (char)reader.Read()); Console.WriteLine("Peek again: " + (char)reader.Peek()); Console.WriteLine("Read again: " + (char)reader.Read()); } } }
Peek
returns the next character without advancing the
position. It returns -1 at end of file, just like Read
.
This method is particularly useful when you need to look ahead in the stream to decide how to process the next characters, such as in parsers.
Reading with Buffer
For performance-critical applications, StreamReader can read blocks of characters into a buffer. This example shows buffer-based reading.
using System; using System.IO; using System.Text; class Program { static void Main() { string filePath = "largefile.txt"; // Create a large sample file var sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.AppendLine($"Line {i + 1}"); } File.WriteAllText(filePath, sb.ToString()); // Read with buffer char[] buffer = new char[128]; using (StreamReader reader = new StreamReader(filePath)) { int charsRead; int totalChars = 0; while ((charsRead = reader.Read(buffer, 0, buffer.Length)) > 0) { totalChars += charsRead; Console.Write($"Read {charsRead} chars: "); Console.WriteLine(new string(buffer, 0, Math.Min(20, charsRead)) + "..."); } Console.WriteLine($"\nTotal characters read: {totalChars}"); } } }
The Read
overload fills a character buffer with data from
the stream. It returns the number of characters actually read.
Buffer reading is more efficient than character-by-character processing for large files. The buffer size can be tuned for optimal performance.
Reading from MemoryStream
StreamReader can read from any Stream, including MemoryStream. This example shows reading text data from memory.
using System; using System.IO; using System.Text; class Program { static void Main() { // Create text in memory string text = "This text is in memory\nSecond line\nThird line"; byte[] bytes = Encoding.UTF8.GetBytes(text); // Read from MemoryStream using (var memoryStream = new MemoryStream(bytes)) using (var reader = new StreamReader(memoryStream)) { Console.WriteLine("Reading from MemoryStream:"); string line; while ((line = reader.ReadLine()) != null) { Console.WriteLine("> " + line); } } } }
The example converts a string to bytes, creates a MemoryStream from those bytes, then reads it with StreamReader. This pattern is useful for processing text data received from network or other sources.
StreamReader works the same way with MemoryStream as with file streams, demonstrating its flexibility with different stream sources.
Source
StreamReader Class Documentation
This tutorial covered reading text data in C# with StreamReader, including line-by-line reading, encodings, buffering, and memory streams. StreamReader is versatile for all text processing needs.
Author
List all C# tutorials.