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 - prefer StreamWriter.

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.