Writing a File: StreamWriter's Defaults
A StreamWriter writes text to a file the way Console writes to the screen. By default it creates the file, or replaces one that's already there. Close it with using, so everything written reaches the disk.
Journeyman · C# · Updated
After this lesson you can
- Write lines to a text file with a StreamWriter in a using statement, knowing that it replaces any file already there
- Save a list of objects as a CSV file, with a header and one line per object
Key takeaways
new StreamWriter(path)creates the file if it isn't there, and replaces it if it is: whatever it held before is gone.- A
StreamWritercollects text in a buffer and writes what's left only when it's closed, so always open it withusing, or the end of your file may never be written. - To save objects as CSV, write a header line, then one line per object with its properties joined by commas.
- Writing can fail too, such as when the file is open in Excel, so it goes in a
trylike reading does. File.WriteAllTextandFile.WriteAllLineswrite a small file in one call, and they also replace any file already there.
Reading used a StreamReader. Writing uses its partner, a StreamWriter, and it feels just like writing to the console: WriteLine and Write, only the text goes into a file instead of onto the screen.
Writing a file
using (StreamWriter writer = new StreamWriter("shopping.txt"))
{
writer.WriteLine("Milk");
writer.WriteLine("Bread");
writer.WriteLine("Coffee");
}
Console.WriteLine(File.ReadAllText("shopping.txt"));
Milk
Bread
Coffee
Out of the box, new StreamWriter(path):
- creates the file if there isn't one, and
- replaces the file if there is one. Whatever it held before is gone.
That's the default. To add to the end of a file instead, see the next lesson.
Why using matters even more here
A StreamWriter doesn't send every line to the disk straight away. It collects text in memory (a buffer) and writes it in larger pieces, because that's much faster. Closing the writer sends whatever is still waiting.
So forget to close it, and the end of your file, or all of it, may never be written:
StreamWriter writer = new StreamWriter("forgotten.txt");
writer.WriteLine("Is anybody there?");
Console.WriteLine( quot;{new FileInfo("forgotten.txt").Length} bytes");
0 bytes
The line is still sitting in the buffer. That's why a writer always goes in a using: when the block ends, even because of an exception, the writer is closed and everything reaches the disk. Here it's a using block with braces; the using StreamWriter writer = ...; declaration you've used before works too, and closes the writer at the end of the enclosing block.
Saving objects as CSV
Saving a list of objects is reading in reverse: a header line, then one line per object, its properties joined with commas.
List<Student> students = new List<Student>
{
new Student("Emily", "Wilson", 3.91m),
new Student("John", "Smith", 2.5m),
new Student("Jane", "Garcia", 3.96m)
};
try
{
using (StreamWriter writer = new StreamWriter("honor_roll.csv"))
{
writer.WriteLine("firstname,lastname,gpa");
foreach (Student student in students)
{
writer.WriteLine( quot;{student.FirstName},{student.LastName},{student.Gpa:0.00}");
}
}
}
catch (IOException ex)
{
Console.WriteLine( quot;Couldn't save: {ex.Message}");
}
Console.WriteLine(File.ReadAllText("honor_roll.csv"));
public class Student
{
public string FirstName { get; }
public string LastName { get; }
public decimal Gpa { get; }
public Student(string firstName, string lastName, decimal gpa)
{
FirstName = firstName;
LastName = lastName;
Gpa = gpa;
}
}
firstname,lastname,gpa
Emily,Wilson,3.91
John,Smith,2.50
Jane,Garcia,3.96
- The header comes first, so the file reads back with Reading a File in C#'s code, and opens neatly in a spreadsheet.
{student.Gpa:0.00}writes every GPA with two decimal places, so2.5is saved as2.50.- Writing can fail too (the disk is full, the file is open in Excel), so it goes in a
trylike reading does.
The one-line shortcuts
For small files, File can write everything in one call. These also create or replace the file, and close it for you:
| Method | Writes |
|---|---|
File.WriteAllText(path, text) |
One string, as it is |
File.WriteAllLines(path, lines) |
Each string in a list or array, each on its own line |
List<string> lines = new List<string> { "firstname,lastname,gpa", "Emily,Wilson,3.91" };
File.WriteAllLines("one_student.csv", lines);
Console.WriteLine(File.ReadAllText("one_student.csv"));
firstname,lastname,gpa
Emily,Wilson,3.91
Reach for a StreamWriter when you're writing as you go, such as one line per object in a loop, and for the shortcuts when you already have all the text.
Check yourself
2 questions to try on the lesson page.
So what
A StreamWriter is Console.WriteLine into a file. It replaces the file by default, and it only finishes writing when it's closed, so always open it with using.