ZetCode

C# StringReader

last modified April 20, 2025

This tutorial explains how to use the StringReader class in C# to read and process string data. StringReader provides methods for reading strings character by character or line by line.

The StringReader class implements a TextReader that reads from a string. It provides methods similar to StreamReader but works directly with strings.

StringReader is useful for parsing string data when you need line-by-line or character-by-character processing. It's often used with StringWriter for building strings.

Basic StringReader Example

This example demonstrates basic usage of StringReader to read a string character by character.

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string text = "Hello StringReader";
        
        using (StringReader reader = new StringReader(text))
        {
            int character;
            while ((character = reader.Read()) != -1)
            {
                Console.Write((char)character);
            }
        }
    }
}

The example creates a StringReader from a string and reads it character by character. The Read() method returns -1 when reaching the end of the string. In this example, we initialize a StringReader with the string "Hello StringReader".

The while loop continues reading characters until Read() returns -1. Each character is cast to char before being printed. This demonstrates the fundamental character-by-character reading capability of StringReader.

Reading Lines with StringReader

StringReader can read strings line by line, which is useful for processing multi-line text.

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string lines = "First line\nSecond line\nThird line";
        
        using (StringReader reader = new StringReader(lines))
        {
            string line;
            int count = 1;
            
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine($"Line {count}: {line}");
                count++;
            }
        }
    }
}

The ReadLine() method returns null when no more lines are available. This example shows how to process a multi-line string. The input string contains three lines separated by newline characters.

The StringReader reads each line sequentially using ReadLine(), which automatically handles the newline characters. The line counter demonstrates how to track line numbers during processing.

Reading Blocks of Characters

StringReader can read blocks of characters into arrays, which is efficient for processing large strings.

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string text = "The quick brown fox jumps over the lazy dog";
        
        using (StringReader reader = new StringReader(text))
        {
            char[] buffer = new char[10];
            int charsRead;
            
            while ((charsRead = reader.Read(buffer, 0, buffer.Length)) > 0)
            {
                Console.WriteLine($"Read {charsRead} chars: " + 
                    new string(buffer, 0, charsRead));
            }
        }
    }
}

The Read(char[], int, int) method reads characters into a buffer array. It returns the number of characters actually read. This example demonstrates reading the string in 10-character chunks.

The buffer array temporarily stores the characters read from the StringReader. The charsRead variable tracks how many characters were actually read in each operation. This approach is memory-efficient for large strings.

Peeking at Characters

StringReader allows peeking at the next character without consuming it using the Peek() method.

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string text = "ABC123";
        
        using (StringReader reader = new StringReader(text))
        {
            int peek = reader.Peek();
            Console.WriteLine($"Peeked: {(char)peek}");
            
            int read = reader.Read();
            Console.WriteLine($"Read: {(char)read}");
        }
    }
}

Peek() returns -1 at the end of the string, just like Read(). This example shows the difference between peeking and reading. The Peek() method allows looking at the next character without advancing the reader's position.

The first character 'A' is peeked at but remains available for reading. The subsequent Read() then consumes this same character. This is useful for lookahead operations when parsing strings.

Combining StringReader and StringWriter

StringReader is often used with StringWriter for string processing pipelines.

Program.cs
using System;
using System.IO;
using System.Text;

class Program
{
    static void Main()
    {
        string input = "line1\nline2\nline3";
        
        using (StringReader reader = new StringReader(input))
        using (StringWriter writer = new StringWriter())
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                writer.WriteLine(line.ToUpper());
            }
            
            Console.WriteLine("Processed output:");
            Console.WriteLine(writer.ToString());
        }
    }
}

This example reads lines from a StringReader, processes them (converts to uppercase), and writes to a StringWriter. The StringReader reads the input string line by line. Each line is converted to uppercase and written to the StringWriter.

The StringWriter accumulates the processed lines in its internal StringBuilder. Finally, the complete processed string is retrieved using ToString(). This demonstrates a common text processing pipeline pattern.

Reading to End of String

The ReadToEnd() method reads all remaining characters from the current position to the end of the string.

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string text = "First part\nSecond part\nThird part";
        
        using (StringReader reader = new StringReader(text))
        {
            // Read and discard first line
            reader.ReadLine();
            
            // Read remaining content
            string remaining = reader.ReadToEnd();
            Console.WriteLine("Remaining content:");
            Console.WriteLine(remaining);
        }
    }
}

This example reads and discards the first line, then reads the entire remaining content. The ReadLine() call advances past the first line. Then ReadToEnd() reads all remaining text from the current position to the end.

This approach is useful when you need to skip a header or preamble in text data before processing the main content. The method is efficient for reading large remaining portions of text.

Handling Empty Strings

This example demonstrates how StringReader behaves with empty strings and different reading methods.

Program.cs
using System;
using System.IO;

class Program
{
    static void Main()
    {
        string empty = "";
        string whitespace = "   ";
        
        Console.WriteLine("Testing empty string:");
        TestReader(empty);
        
        Console.WriteLine("\nTesting whitespace string:");
        TestReader(whitespace);
    }
    
    static void TestReader(string input)
    {
        using (StringReader reader = new StringReader(input))
        {
            Console.WriteLine($"Read(): {reader.Read()}");
            Console.WriteLine($"Peek(): {reader.Peek()}");
            Console.WriteLine($"ReadLine(): {reader.ReadLine() ?? "null"}");
            Console.WriteLine($"ReadToEnd(): \"{reader.ReadToEnd()}\"");
        }
    }
}

The example shows the return values of various StringReader methods with empty and whitespace strings. With an empty string, Read() and Peek() immediately return -1. ReadLine() returns null, and ReadToEnd() returns an empty string.

With whitespace, Read() returns the first space character, Peek() does the same without advancing, ReadLine() returns the whitespace string, and ReadToEnd() returns the entire whitespace string. This demonstrates edge case behavior.

Source

StringReader Class Documentation

This tutorial covered reading string data in C# with StringReader, including character-by-character reading, line reading, and block reading techniques.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all C# tutorials.