C# StreamWriter
last modified April 20, 2025
This tutorial explains how to use the StreamWriter class in C# to write text data to files. StreamWriter provides methods for writing text to streams with various encodings.
The StreamWriter class implements a TextWriter for writing characters to a stream in a particular encoding. It's commonly used for writing text files.
StreamWriter
handles text encoding automatically and provides
efficient buffered writing. It's often paired with StreamReader
for reading text files.
Basic StreamWriter Example
This example demonstrates writing text to a file using StreamWriter. It shows the simplest way to create and write to a text file.
using System; using System.IO; class Program { static void Main() { // Create a file and write text to it using (StreamWriter writer = new StreamWriter("example.txt")) { writer.WriteLine("This is the first line."); writer.WriteLine("This is the second line."); writer.Write("This is "); writer.Write("a single line."); } Console.WriteLine("Text written to file successfully."); } }
The example creates a new file named "example.txt" and writes three lines of
text. The using
statement ensures proper resource cleanup.
WriteLine
adds a newline after each string, while
Write
does not.
The file is automatically closed when the using
block ends.
This is the recommended way to work with file streams as it handles
disposal automatically, even if an exception occurs.
Appending to an Existing File
StreamWriter can append text to existing files instead of overwriting them. This example shows how to add content to an existing file.
using System; using System.IO; class Program { static void Main() { // Append text to an existing file using (StreamWriter writer = new StreamWriter("log.txt", true)) { writer.WriteLine($"Log entry: {DateTime.Now}"); writer.WriteLine("Application started successfully."); writer.WriteLine(); } Console.WriteLine("Log entry appended to file."); } }
The second parameter in the StreamWriter constructor specifies whether to
append to the file. Setting it to true
preserves existing
content. This is particularly useful for log files where you want to
maintain a history of entries.
Each run of this program will add new log entries to the file without
affecting previous content. The empty WriteLine
adds a
blank line between entries for better readability.
Specifying File Encoding
StreamWriter allows specifying text encoding when writing files. This example demonstrates writing with UTF-8 and UTF-16 encodings.
using System; using System.IO; using System.Text; class Program { static void Main() { // Write with UTF-8 encoding (default) using (StreamWriter writer = new StreamWriter("utf8.txt", false, Encoding.UTF8)) { writer.WriteLine("UTF-8 encoded text: Café"); } // Write with UTF-16 encoding using (StreamWriter writer = new StreamWriter("utf16.txt", false, Encoding.Unicode)) { writer.WriteLine("UTF-16 encoded text: Café"); } Console.WriteLine("Files written with different encodings."); } }
The third parameter in the StreamWriter constructor specifies the text encoding. UTF-8 is the default if no encoding is specified. Different encodings handle special characters and international text differently.
UTF-8 is more space-efficient for ASCII characters, while UTF-16 might be better for languages with non-Latin characters. The choice depends on your specific requirements and the expected content.
Writing Formatted Text
StreamWriter supports formatted writing similar to Console.WriteLine. This example shows how to write formatted strings to a file.
using System; using System.IO; class Program { static void Main() { string product = "Coffee"; decimal price = 4.99m; int quantity = 10; using (StreamWriter writer = new StreamWriter("receipt.txt")) { writer.WriteLine("RECEIPT"); writer.WriteLine("-------"); writer.WriteLine("Date: {0:d}", DateTime.Today); writer.WriteLine("Product: {0}", product); writer.WriteLine("Price: {0:C}", price); writer.WriteLine("Quantity: {0}", quantity); writer.WriteLine("Total: {0:C}", price * quantity); } Console.WriteLine("Formatted receipt written to file."); } }
The example uses composite formatting with placeholders ({0}, {1}, etc.) to create a structured receipt. Format specifiers like :d for dates and :C for currency make the output more readable.
This approach is useful for generating structured documents, reports, or any output where consistent formatting is important. The same formatting options available in Console.WriteLine are supported.
Flushing and AutoFlush
StreamWriter buffers writes by default. This example demonstrates manual flushing and the AutoFlush property.
using System; using System.IO; class Program { static void Main() { // With default buffering using (StreamWriter writer = new StreamWriter("buffered.txt")) { writer.WriteLine("This may not appear immediately."); Console.WriteLine("Check file - content may not be there yet."); writer.Flush(); // Force write to disk Console.WriteLine("Now content should be in file."); } // With AutoFlush enabled using (StreamWriter writer = new StreamWriter("autoflush.txt")) { writer.AutoFlush = true; writer.WriteLine("This appears immediately after each write."); Console.WriteLine("Content should be in file already."); } } }
Flush
forces any buffered data to be written to the file.
AutoFlush = true
makes this happen automatically after each
write. Buffering improves performance by reducing disk I/O operations.
Manual flushing is useful when you need to ensure data is written at specific points. AutoFlush is convenient but may impact performance with many small writes. Choose the appropriate approach based on your needs.
Writing to MemoryStream
StreamWriter can write to any Stream, including MemoryStream. This example shows writing text to memory instead of a file.
using System; using System.IO; using System.Text; class Program { static void Main() { using (MemoryStream memoryStream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(memoryStream, Encoding.UTF8, 1024, true)) { writer.WriteLine("This text is written to memory."); writer.WriteLine("Current time: {0:T}", DateTime.Now); } // Read back from the MemoryStream memoryStream.Position = 0; using (StreamReader reader = new StreamReader(memoryStream)) { string content = reader.ReadToEnd(); Console.WriteLine("Memory content:"); Console.WriteLine(content); } } } }
The example writes text to a MemoryStream, then reads it back. The StreamWriter constructor parameters control encoding, buffer size, and leave-open behavior. This technique is useful for in-memory text processing.
MemoryStreams are often used in unit testing, network communication,
or when you need to process text without creating physical files. The
Position = 0
reset is necessary before reading back the
content.
Writing Asynchronously
StreamWriter supports asynchronous operations for better performance in I/O-bound applications. This example shows async file writing.
using System; using System.IO; using System.Threading.Tasks; class Program { static async Task Main() { try { using (StreamWriter writer = new StreamWriter("async.txt")) { await writer.WriteLineAsync("First line written asynchronously."); await writer.WriteAsync("This is "); await writer.WriteLineAsync("also async."); await writer.FlushAsync(); } Console.WriteLine("Asynchronous write completed."); } catch (Exception ex) { Console.WriteLine($"Error: {ex.Message}"); } } }
Async methods (WriteLineAsync
, WriteAsync
,
FlushAsync
) don't block the calling thread during I/O
operations. This improves responsiveness in GUI applications and
scalability in server applications.
The async/await
pattern makes asynchronous code almost
as simple as synchronous code. Always handle potential exceptions
when performing file I/O operations.
Source
StreamWriter Class Documentation
This tutorial covered writing text files in C# with StreamWriter, including basic writing, appending, encoding, formatting, and async operations.
Author
List all C# tutorials.