Chapter 21: File I/O and Serialization
Until now, all our data lived only in memory – as soon as the program stopped, poof! Everything was gone. Now we’re going to learn how to save data to files and read it back, and how to save complex objects (like lists of students, settings, game progress…) as JSON or XML – the two most popular formats in the world.
I’m going to explain everything very slowly, step by step, with tons of real-life examples, clear analogies, and practical mini-projects — just like we’re sitting together in Hyderabad looking at the same screen. Let’s dive in! 🚀
1. Reading and Writing Files – The Basics
C# gives us several ways to work with files. We’ll start with the easiest and most common ones.
A. The Simplest Way: File Class (High-Level Helpers)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
using System.IO; // Don't forget this! // 1. Write text to a file (overwrites if exists) File.WriteAllText("welcome.txt", "Hello from Hyderabad! 🌆\nWelcome to C# File I/O!"); // 2. Read entire file as one string string content = File.ReadAllText("welcome.txt"); Console.WriteLine(content); // 3. Write multiple lines string[] lines = new string[] { "Line 1: Learning C# is fun!", "Line 2: File handling is super useful.", "Line 3: See you in the next chapter! 🚀" }; File.WriteAllLines("notes.txt", lines); // 4. Read all lines into array string[] readLines = File.ReadAllLines("notes.txt"); foreach (string line in readLines) { Console.WriteLine(line); } // 5. Append (add without overwriting) File.AppendAllText("log.txt", $"[{DateTime.Now}] Application started\n"); |
Important: File.WriteAllText() and WriteAllLines() overwrite the file if it already exists. Use AppendAllText() or AppendAllLines() to add without losing previous content.
B. Reading/Writing Line by Line – StreamReader & StreamWriter (More Control)
When you need to read or write huge files or process line by line (recommended for big files).
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Writing line by line using (StreamWriter writer = new StreamWriter("shoppinglist.txt")) { writer.WriteLine("Milk"); writer.WriteLine("Bread"); writer.WriteLine("Eggs"); writer.WriteLine("Coffee"); } // Reading line by line using (StreamReader reader = new StreamReader("shoppinglist.txt")) { string line; while ((line = reader.ReadLine()) != null) { Console.WriteLine($"Item: {line}"); } } |
Why use using? It automatically closes the file when you’re done – very important to avoid file locks!
2. Checking If File Exists, Deleting, Copying, Moving
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
string path = "data.txt"; // Check if exists if (File.Exists(path)) { Console.WriteLine("File exists!"); } else { Console.WriteLine("File does NOT exist."); } // Delete if (File.Exists(path)) File.Delete(path); // Copy File.Copy("source.txt", "backup.txt", true); // true = overwrite if exists // Move (rename or move to another folder) File.Move("oldname.txt", "newfolder/newname.txt"); |
3. Serialization – Saving Objects to Files (JSON & XML)
Serialization = turning an object (or list of objects) into a string or byte stream that you can save to a file or send over the internet. Deserialization = turning that string back into an object.
A. JSON Serialization – The Modern Standard (System.Text.Json – Built-in since .NET Core 3)
Recommended in 2026: System.Text.Json (fast, secure, built-in)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
using System.Text.Json; // Built-in – no extra package needed! class Person { public string Name { get; set; } public int Age { get; set; } public string City { get; set; } public List<string> Hobbies { get; set; } } // Create object Person person = new Person { Name = "Webliance", Age = 25, City = "Hyderabad", Hobbies = new List<string> { "Coding", "Reading", "Cricket" } }; // Serialize to JSON string string json = JsonSerializer.Serialize(person, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine(json); // Save to file File.WriteAllText("person.json", json); // Read back and deserialize string readJson = File.ReadAllText("person.json"); Person loadedPerson = JsonSerializer.Deserialize<Person>(readJson); Console.WriteLine($"Loaded: {loadedPerson.Name}, {loadedPerson.Age} from {loadedPerson.City}"); Console.WriteLine("Hobbies: " + string.Join(", ", loadedPerson.Hobbies)); |
Output JSON:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "Name": "Webliance", "Age": 25, "City": "Hyderabad", "Hobbies": [ "Coding", "Reading", "Cricket" ] } |
B. Newtonsoft.Json (Json.NET) – Still Very Popular (Especially in Older Projects)
Add NuGet package: Newtonsoft.Json
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
using Newtonsoft.Json; // Serialize string jsonNewton = JsonConvert.SerializeObject(person, Formatting.Indented); File.WriteAllText("person-newton.json", jsonNewton); // Deserialize Person loadedNewton = JsonConvert.DeserializeObject<Person>(File.ReadAllText("person-newton.json")); |
Both libraries are great, but in new projects (2026) → prefer System.Text.Json (faster, built-in, more secure by default).
4. Mini-Project: Todo List App with File Saving
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
class TodoItem { public string Task { get; set; } public bool IsDone { get; set; } public DateTime Created { get; set; } } class TodoManager { private const string FILE_PATH = "todos.json"; private List<TodoItem> todos = new List<TodoItem>(); public void Add(string task) { todos.Add(new TodoItem { Task = task, IsDone = false, Created = DateTime.Now }); Save(); } public void MarkDone(int index) { if (index >= 0 && index < todos.Count) { todos[index].IsDone = true; Save(); } } public void ShowAll() { for (int i = 0; i < todos.Count; i++) { var t = todos[i]; string status = t.IsDone ? "[DONE]" : "[PENDING]"; Console.WriteLine($"{i + 1}. {status} {t.Task} (Created: {t.Created:dd-MMM-yyyy})"); } } private void Save() { string json = JsonSerializer.Serialize(todos, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(FILE_PATH, json); } public void Load() { if (File.Exists(FILE_PATH)) { string json = File.ReadAllText(FILE_PATH); todos = JsonSerializer.Deserialize<List<TodoItem>>(json) ?? new List<TodoItem>(); } } } // Usage TodoManager manager = new TodoManager(); manager.Load(); manager.Add("Finish C# tutorial"); manager.Add("Buy groceries"); manager.Add("Call mom"); manager.MarkDone(0); manager.ShowAll(); |
Output after running a few times:
|
0 1 2 3 4 5 6 7 8 |
1. [DONE] Finish C# tutorial (Created: 21-Jan-2026) 2. [PENDING] Buy groceries (Created: 21-Jan-2026) 3. [PENDING] Call mom (Created: 21-Jan-2026) |
Summary – What We Learned Today
- File I/O → File.WriteAllText(), File.ReadAllText(), StreamWriter, StreamReader
- Check/Delete/Copy/Move → File.Exists(), File.Delete(), File.Copy(), File.Move()
- JSON Serialization → System.Text.Json (built-in) or Newtonsoft.Json (popular)
- Save & Load entire objects/lists → super easy with JsonSerializer.Serialize() / Deserialize()
- Always use using blocks for file streams → auto-closes files
Your Homework (Super Practical!)
- Create a new console project called FileAndJsonMaster
- Make a Personal Diary App that:
- Lets user add diary entries (date + text)
- Saves all entries to diary.json
- Loads them when program starts
- Shows all entries sorted by date
- Lets user search entries by keyword
- Bonus: Add ability to delete an entry by number and save again
Next lesson: Asynchronous Programming (async/await) – we’re going to learn how to make your programs do many things at once without freezing!
You’re doing absolutely fantastic! 🎉 Any part confusing? Want more examples with XML serialization or binary files? Just tell me — I’m right here for you! 💙
