Back to Curriculum

File I/O and Serialization

📚 Lesson 14 of 15 ⏱️ 45 min

File I/O and Serialization

45 min

C# provides comprehensive file I/O capabilities through System.IO namespace, enabling reading and writing files, directories, and streams. File operations include reading/writing text and binary data, directory management, and path manipulation. Understanding file I/O enables persistent data storage. File I/O is essential for most applications.

JSON serialization is popular for data exchange, enabling conversion between objects and JSON text. System.Text.Json (modern) and Newtonsoft.Json (popular) provide JSON serialization. JSON is human-readable, language-agnostic, and widely supported. Understanding JSON serialization enables data exchange. JSON is the standard for web APIs.

Binary serialization preserves object state by converting objects to binary format, enabling storage and transmission of complex object graphs. Binary serialization is faster and more compact than text formats but less portable. Understanding binary serialization enables efficient data storage. Binary serialization is useful for performance-critical scenarios.

Streams provide efficient data handling by enabling sequential reading/writing of data without loading everything into memory. Stream classes (FileStream, MemoryStream, NetworkStream) abstract data sources. Streams enable processing large files efficiently. Understanding streams enables scalable I/O. Streams are fundamental to I/O operations.

Async file I/O methods (ReadAllTextAsync, WriteAllTextAsync) enable non-blocking file operations, preventing UI freezing and improving scalability. Async I/O is essential for responsive applications. Understanding async I/O enables modern file operations. Async I/O is the recommended approach.

Best practices include using async I/O methods, disposing streams properly (using statement), handling file exceptions, using appropriate serialization formats, and validating file paths. Understanding file I/O and serialization enables robust data persistence. File I/O is essential for most applications.

Key Concepts

  • C# provides comprehensive file I/O through System.IO.
  • JSON serialization is popular for data exchange.
  • Binary serialization preserves object state efficiently.
  • Streams provide efficient sequential data handling.
  • Async I/O methods enable non-blocking file operations.

Learning Objectives

Master

  • Reading and writing files with System.IO
  • Serializing objects to JSON
  • Using streams for efficient I/O
  • Implementing async file operations

Develop

  • Understanding data persistence strategies
  • Designing efficient I/O operations
  • Appreciating serialization's role in data exchange

Tips

  • Use async I/O methods (ReadAllTextAsync, WriteAllTextAsync) for non-blocking operations.
  • Use 'using' statement to ensure streams are disposed.
  • Use JSON for human-readable, portable data exchange.
  • Use streams for processing large files efficiently.

Common Pitfalls

  • Not using async I/O, blocking threads unnecessarily.
  • Not disposing streams, causing resource leaks.
  • Not handling file exceptions, causing crashes.
  • Using binary serialization when JSON would be better.

Summary

  • C# provides comprehensive file I/O capabilities.
  • JSON serialization enables data exchange.
  • Streams provide efficient data handling.
  • Async I/O enables non-blocking operations.
  • Understanding file I/O enables data persistence.

Exercise

Demonstrate file operations and JSON serialization.

using System;
using System.IO;
using System.Text.Json;
using System.Collections.Generic;

[Serializable]
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public List<string> Hobbies { get; set; } = new List<string>();
}

class Program
{
    static void Main(string[] args)
    {
        var person = new Person
        {
            Name = "Alice",
            Age = 30,
            Hobbies = { "Reading", "Coding", "Hiking" }
        };
        
        // JSON serialization
        string json = JsonSerializer.Serialize(person, new JsonSerializerOptions 
        { 
            WriteIndented = true 
        });
        
        Console.WriteLine("JSON serialization:");
        Console.WriteLine(json);
        
        // Write to file
        File.WriteAllText("person.json", json);
        Console.WriteLine("\nData written to person.json");
        
        // Read from file and deserialize
        string jsonFromFile = File.ReadAllText("person.json");
        var deserializedPerson = JsonSerializer.Deserialize<Person>(jsonFromFile);
        
        Console.WriteLine("\nDeserialized person:");
        Console.WriteLine($"Name: {deserializedPerson.Name}");
        Console.WriteLine($"Age: {deserializedPerson.Age}");
        Console.WriteLine("Hobbies:");
        foreach (var hobby in deserializedPerson.Hobbies)
        {
            Console.WriteLine($"  - {hobby}");
        }
        
        // Stream operations
        using (var writer = new StreamWriter("data.txt"))
        {
            writer.WriteLine("Line 1");
            writer.WriteLine("Line 2");
            writer.WriteLine("Line 3");
        }
        
        using (var reader = new StreamReader("data.txt"))
        {
            Console.WriteLine("\nFile contents:");
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }
    }
}

Code Editor

Output