C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
201: StreamReader and StreamWriter
Wait, why bother with these when File.WriteAllText exists?
I get this question a lot. If you just need to dump a small string into a file, File.WriteAllText is great because it's a one-liner. But here is the reality: in professional software, you're often dealing with data that is too large to fit comfortably in memory. If you try to use ReadAllText on a 2GB log file, your application is going to crash with an OutOfMemoryException.
StreamReader and StreamWriter are different because they don't load the whole file at once. They act like a straw, sipping data one piece at a time. This keeps your memory footprint low regardless of whether the file is ten lines or ten million lines long.
How do I add new data to a file without overwriting what's already there?
By default, StreamWriter is aggressive—it wipes the file clean the moment you open it. If you're building something like a combat log for a game or a system audit trail, that's the last thing you want. To fix this, you pass a boolean true as the second argument in the constructor to enable "append mode."
string logPath = "session_log.txt"; string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); // The 'true' here tells C# to append to the file instead of overwriting it using (StreamWriter writer = new StreamWriter(logPath, true)) { writer.WriteLine($"[{timestamp}] Player entered the Forbidden Forest."); writer.WriteLine($"[{timestamp}] Player picked up a Rusty Sword."); }I always use the
usingstatement here. It ensures the file is closed and the buffer is flushed to disk immediately, even if the code throws an error. If you forget it, you might find that your file stays empty because the data is still sitting in a memory buffer waiting to be written.What's the cleanest way to read a file line-by-line?
You don't know exactly how many lines are in a file until you've actually reached the end. The standard pattern I use is a
whileloop that keeps callingReadLine()until it returnsnull.nullis C#'s way of telling you, "That's it, you've hit the bottom of the file."Let's say we want to read that log file we just created and search for a specific keyword:
string logPath = "session_log.txt"; string searchKeyword = "Rusty Sword"; using (StreamReader reader = new StreamReader(logPath)) { string line; // Read one line at a time until the end of the stream while ((line = reader.ReadLine()) != null) { if (line.Contains(searchKeyword)) { Console.WriteLine($"Found it: {line}"); } } }Notice how we declare
string lineoutside the loop. We do this so the variable is available for theifcheck inside the loop body. It's a tight, efficient way to process huge amounts of text without stressing the CPU or RAM.
📋 Practical Task
Exercise: Player Inventory Save/Load System
You are building a simple RPG. You need to create a system that saves a player's inventory to a text file and then loads it back into the game when the program restarts.
- Create a
List<string>containing at least five items (e.g., "Health Potion", "Iron Shield", "Magic Map"). - Use a
StreamWriterto save each item from the list into a file namedinventory.txt, ensuring each item is on its own line. - Clear your list (or create a new empty one).
- Use a
StreamReaderto read theinventory.txtfile line-by-line and add each item back into your list. - Finally, print the recovered list to the console to verify that the load was successful.
There are no comments for now.