Text File Writing
Vaibhav • September 10, 2025
In the previous article, we explored how to read text files using various techniques like File.ReadAllText
, File.ReadLines
, and StreamReader
. Now it’s time to flip the direction - writing data to text files.
Whether you're logging events, saving user input, or exporting results, writing to files is a fundamental part
of building real-world applications. In this article, we’ll cover the different ways to write text files in C#,
how to append vs overwrite, how to handle encoding, and how to write efficiently and safely.
Writing a Full String to a File
The simplest way to write text to a file is using File.WriteAllText
. This
method creates the file if it doesn’t exist, and overwrites it if it does.
string message = "Hello, world!";
File.WriteAllText("output.txt", message);
This writes the entire string to output.txt
. If the file already exists, its
contents will be replaced. If it doesn’t exist, it will be created automatically.
WriteAllText
is best for small files or when you
want to replace the entire content. It’s not suitable for appending or writing incrementally.
Appending Text to a File
To add new content to the end of an existing file without erasing its current contents, use File.AppendAllText
. This is commonly used for logging or journaling.
string logEntry = $"Log at {DateTime.Now}\n";
File.AppendAllText("log.txt", logEntry);
This adds a new line to log.txt
each time the code runs. If the file doesn’t
exist, it will be created.
Use AppendAllText
for logs and audit trails. It preserves
history and avoids accidental data loss.
Writing Multiple Lines
If you have a collection of strings and want to write each one as a separate line, use File.WriteAllLines
. This method takes an IEnumerable<string>
and writes each item as a line.
string[] fruits = { "Apple", "Banana", "Cherry" };
File.WriteAllLines("fruits.txt", fruits);
This creates a file with each fruit on its own line. It’s a clean and readable way to export lists or logs.
Appending Multiple Lines
To append multiple lines, you can use File.AppendAllLines
. It works similarly
to WriteAllLines
but adds to the end of the file.
List<string> newFruits = new List<string> { "Mango", "Papaya" };
File.AppendAllLines("fruits.txt", newFruits);
This adds new entries to the existing file without overwriting previous content. It’s useful for incremental data collection.
Using StreamWriter for More Control
For more advanced scenarios - like writing with custom encoding, buffering, or formatting - use StreamWriter
. This class gives you full control over how text is written.
using StreamWriter writer = new StreamWriter("report.txt");
writer.WriteLine("Report Title");
writer.WriteLine("Generated on: " + DateTime.Now);
writer.WriteLine("Summary:");
writer.WriteLine("Everything is working smoothly.");
Each call to WriteLine
adds a new line to the file. You can also use Write
to write without a newline.
StreamWriter
implements IDisposable
, so it
should be used with a using
statement to ensure the file is closed
properly.
Writing with Encoding
By default, StreamWriter
uses UTF-8 encoding. If you need to write in a
different encoding (e.g., for legacy systems), you can specify it explicitly:
using StreamWriter writer = new StreamWriter("legacy.txt", false, Encoding.GetEncoding("ISO-8859-1"));
writer.WriteLine("Legacy content here.");
This writes the file using ISO-8859-1 encoding. The second parameter (false
)
indicates that the file should be overwritten.
Appending with StreamWriter
To append using StreamWriter
, set the second parameter to true
:
using StreamWriter writer = new StreamWriter("log.txt", true);
writer.WriteLine($"Appended at {DateTime.Now}");
This adds a new line to the end of log.txt
without erasing its contents.
Writing Formatted Output
You can use string interpolation or string.Format
to write structured data:
string name = "Vaibhav";
int score = 95;
using StreamWriter writer = new StreamWriter("scores.txt");
writer.WriteLine($"Name: {name}, Score: {score}");
This creates a readable line with labeled values. It’s useful for exporting reports or summaries.
Writing Lists and Tables
To write tabular data, you can format each line with delimiters like commas or tabs:
List<string> lines = new List<string>
{
"Name,Score",
"Vaibhav,95",
"Aparna,88"
};
File.WriteAllLines("results.csv", lines);
This creates a CSV file that can be opened in Excel or processed by other tools. Each line represents a row.
Handling Exceptions
File writing can fail due to permission issues, disk errors, or locked files. Always wrap your writing logic in
a try-catch
block:
try
{
File.WriteAllText("readonly.txt", "Trying to write...");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("Access denied.");
}
catch (IOException ex)
{
Console.WriteLine($"I/O error: {ex.Message}");
}
This ensures your application handles errors gracefully and informs the user of what went wrong.
Writing to Temporary Files
For intermediate data or testing, you can write to temporary files using Path.GetTempFileName
:
string tempFile = Path.GetTempFileName();
File.WriteAllText(tempFile, "Temporary data");
Console.WriteLine($"Written to: {tempFile}");
This creates a uniquely named file in the system’s temp directory. It’s useful for sandboxed operations or debugging.
Performance Tips
Writing files is generally fast, but performance can degrade with frequent writes or large data. Here are some tips:
- Use
StreamWriter
with buffering for large files. - Avoid opening and closing files repeatedly - batch your writes.
- Use
AppendAllText
sparingly in tight loops - preferStreamWriter
.
If you’re writing thousands of lines, use StreamWriter
and
keep the file open during the loop. This avoids repeated disk access.
Summary
Writing text files in C# is simple but powerful. You’ve learned how to write full strings, append lines, use
StreamWriter
for advanced control, handle encoding, and manage exceptions.
These techniques are essential for logging, exporting, and saving data in real-world applications. In the next
article, we’ll explore binary file operations - how to write and read raw bytes for performance-critical or
non-textual data.