Vai al contenuto

Parco Auto 2: salvare e caricare i dati

I dati non spariscono piΓΉ alla chiusura del programma: StreamWriter e StreamReader, file TXT e CSV, caricamento automatico all'avvio e gestione degli errori.

Riprendi il progetto della lezione Parco Auto 1: classi e oggetti: hai la classe Automobile, la lista listaAuto e il form con aggiungi, modifica, elimina e ordina. Funziona tutto… finchΓ© non chiudi il programma.

Salvare i Dati su File - Guida Dettagliata

Quando chiudi il programma, tutti i dati spariscono! Per evitare questo, impariamo a salvare il parco auto su file. Quando riapri il programma, potrai ricaricare i dati.

πŸ“– Cos'Γ¨ un File e Come Funziona

Un file è come un quaderno dove scrivi informazioni che vuoi conservare. Quando spegni il computer, il quaderno rimane lì con tutto quello che hai scritto!

🎯 Analogia Semplice:

  • RAM (memoria temporanea): Una lavagna che si cancella quando spegni il PC
  • FILE (memoria permanente): Un quaderno che rimane anche dopo
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ QUANDO IL PROGRAMMA È APERTO:      β”‚
β”‚                                     β”‚
β”‚ RAM (Lavagna)                       β”‚
β”‚ β”œβ”€β”€ List<Automobile> listaAuto      β”‚
β”‚ β”‚   β”œβ”€β”€ Fiat 500                    β”‚
β”‚ β”‚   β”œβ”€β”€ BMW Serie 3                 β”‚
β”‚ β”‚   └── Tesla Model 3               β”‚
β”‚                                     β”‚
β”‚ FILE (Quaderno)                     β”‚
β”‚ └── parco_auto.txt (vuoto o vecchio)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ QUANDO CLICCHI "Salva":             β”‚
β”‚                                     β”‚
β”‚ RAM β†’ COPIA β†’ FILE                  β”‚
β”‚                                     β”‚
β”‚ FILE (Quaderno)                     β”‚
β”‚ └── parco_auto.txt                  β”‚
β”‚     Fiat 500 - 1200cc - Benzina     β”‚
β”‚     BMW Serie 3 - 2000cc - Diesel   β”‚
β”‚     Tesla Model 3 - 0cc - Elettrica β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ QUANDO CHIUDI IL PROGRAMMA:         β”‚
β”‚                                     β”‚
β”‚ RAM (Lavagna)                       β”‚
β”‚ └── [TUTTO CANCELLATO] ❌           β”‚
β”‚                                     β”‚
β”‚ FILE (Quaderno)                     β”‚
β”‚ └── parco_auto.txt βœ… RIMANE!       β”‚
β”‚     Fiat 500 - 1200cc - Benzina     β”‚
β”‚     BMW Serie 3 - 2000cc - Diesel   β”‚
β”‚     Tesla Model 3 - 0cc - Elettrica β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Metodo 1: Salvare in Formato TXT (Leggibile)

  1. Aggiungi il Pulsante di Salvataggio
  • Trascina un Button nel form
  • Chiamalo btnSalvaTXT
  • Imposta la proprietΓ  Text su "Salva in TXT"
  1. Codice per Salvare - Spiegato Riga per Riga

Salvataggio in TXT - Versione Commentata

// In cima al file, aggiungi questo:
using System.IO;  // Necessario per lavorare con i file!

// ═══════════════════════════════════════
// EVENTO: Salva in TXT
// ═══════════════════════════════════════
private void btnSalvaTXT_Click(object sender, EventArgs e)
{
    // STEP 1: Usa try-catch per gestire eventuali errori
    // (es: disco pieno, permessi mancanti, ecc.)
    try
    {
        // STEP 2: Crea/Apri il file per scrivere
        // "parco_auto.txt" Γ¨ il nome del file
        // Se non esiste, viene creato
        // Se esiste, viene sovrascritto
        using (StreamWriter scrittore = new StreamWriter("parco_auto.txt"))
        {
            // STEP 3: Scrivi l'intestazione
            scrittore.WriteLine("═══════════════════════════════════════");
            scrittore.WriteLine("     PARCO AUTO - ELENCO COMPLETO");
            scrittore.WriteLine("═══════════════════════════════════════");
            scrittore.WriteLine("");  // Riga vuota

            // STEP 4: Scrivi ogni auto
            int numero = 1;  // Contatore per numerare le auto

            foreach (Automobile auto in listaAuto)
            {
                // Scrivi il numero e i dati dell'auto
                scrittore.WriteLine($"{numero}. {auto.Stampa()}");
                scrittore.WriteLine("");  // Riga vuota dopo ogni auto

                numero++;  // Passa alla prossima auto
            }

            // STEP 5: Scrivi il totale
            scrittore.WriteLine("───────────────────────────────────────");
            scrittore.WriteLine($"Totale auto: {listaAuto.Count}");
            scrittore.WriteLine("═══════════════════════════════════════");

        } // ← Il file viene chiuso automaticamente qui!

        // STEP 6: Mostra messaggio di successo
        MessageBox.Show("Parco auto salvato nel file parco_auto.txt!",
                      "Salvataggio Completato",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Information);
    }
    catch (Exception errore)
    {
        // Se qualcosa va storto, mostra il messaggio di errore
        MessageBox.Show($"Errore durante il salvataggio: {errore.Message}",
                      "Errore",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Error);
    }
}

πŸ“„ Come Appare il File Salvato

parco_auto.txt (puoi aprirlo con Notepad)

═══════════════════════════════════════
     PARCO AUTO - ELENCO COMPLETO
═══════════════════════════════════════

1. Fiat 500 - 1200cc - Benzina

2. BMW Serie 3 - 2000cc - Diesel

3. Tesla Model 3 - 0cc - Elettrica

───────────────────────────────────────
Totale auto: 3
═══════════════════════════════════════

πŸ” Dove Trovare il File?

  1. Apri Esplora Risorse
  2. Vai alla cartella del tuo progetto (es: C:\Users\TuoNome\source\repos\ParcoAuto)
  3. Apri la cartella bin
  4. Apri la cartella Debug
  5. Troverai il file parco_auto.txt
C:\
└── Users\
    └── TuoNome\
        └── source\
            └── repos\
                └── ParcoAuto\         ← Cartella progetto
                    └── bin\
                        └── Debug\
                            └── parco_auto.txt  ← QUI!

Metodo 2: Salvare in Formato CSV (Excel)

Il formato CSV (Comma-Separated Values) Γ¨ perfetto se vuoi aprire i dati con Excel o fare calcoli.

  1. Aggiungi il Pulsante CSV
  • Trascina un altro Button nel form
  • Chiamalo btnSalvaCSV
  • Imposta la proprietΓ  Text su "Salva in CSV"
  1. Codice per CSV - Versione Semplificata

Salvataggio in CSV

// ═══════════════════════════════════════
// EVENTO: Salva in CSV
// ═══════════════════════════════════════
private void btnSalvaCSV_Click(object sender, EventArgs e)
{
    try
    {
        // Apri/Crea il file CSV
        using (StreamWriter scrittore = new StreamWriter("parco_auto.csv"))
        {
            // STEP 1: Scrivi l'intestazione (nomi delle colonne)
            // Usiamo il punto e virgola (;) come separatore
            scrittore.WriteLine("Modello;Cilindrata;Carburante");

            // STEP 2: Scrivi ogni auto come una riga
            foreach (Automobile auto in listaAuto)
            {
                // Costruisci la riga con i dati separati da ;
                string riga = $"{auto.Modello};{auto.Cilindrata};{auto.Carburante}";
                scrittore.WriteLine(riga);
            }
        }

        // Mostra messaggio di successo
        MessageBox.Show("File CSV salvato! Puoi aprirlo con Excel.",
                      "Salvataggio Completato",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Information);
    }
    catch (Exception errore)
    {
        MessageBox.Show($"Errore: {errore.Message}",
                      "Errore",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Error);
    }
}

πŸ“Š Come Appare il File CSV

parco_auto.csv (si apre con Excel)

Modello;Cilindrata;Carburante
Fiat 500;1200;Benzina
BMW Serie 3;2000;Diesel
Tesla Model 3;0;Elettrica

Quando apri questo file con Excel, vedrai i dati organizzati in colonne, pronti per essere modificati o usati per creare grafici!

Concetti Chiave - StreamWriter Spiegato Semplice

πŸ“ Cos'Γ¨ StreamWriter?

StreamWriter è uno "scrittore di file". È come una penna che scrive sul tuo quaderno (file).

// Crea lo "scrittore" e apri il file
using (StreamWriter scrittore = new StreamWriter("miofile.txt"))
{
    // Scrivi una riga e vai a capo
    scrittore.WriteLine("Prima riga");

    // Scrivi senza andare a capo
    scrittore.Write("Seconda ");
    scrittore.Write("riga");

    // Vai a capo manualmente
    scrittore.WriteLine("");  // Riga vuota

} // ← Il file viene chiuso automaticamente qui!

🎯 I Due Metodi Principali:

Metodo Cosa Fa Esempio
WriteLine() Scrive e va a capo scrittore.WriteLine("Ciao");
Write() Scrive senza andare a capo scrittore.Write("Ciao");

πŸ’‘ PerchΓ© "using"?

Il blocco using Γ¨ importantissimo! Garantisce che il file venga chiuso correttamente anche se succede un errore. Senza using, il file potrebbe rimanere bloccato!

// ❌ MODO SBAGLIATO (senza using):
StreamWriter scrittore = new StreamWriter("file.txt");
scrittore.WriteLine("Test");
scrittore.Close();  // Se c'Γ¨ un errore prima, il file non si chiude!

// βœ… MODO CORRETTO (con using):
using (StreamWriter scrittore = new StreamWriter("file.txt"))
{
    scrittore.WriteLine("Test");
} // ← Si chiude SEMPRE automaticamente, anche con errori!

🎬 Cosa Succede Dietro le Quinte:

// Quando scrivi questo:
using (StreamWriter sw = new StreamWriter("file.txt"))
{
    sw.WriteLine("Ciao");
    sw.WriteLine("Mondo");
}

// Succede questo passo-passo:

// 1. Crea un nuovo file "file.txt" (o lo svuota se esiste)
// 2. Apri il file in modalitΓ  scrittura
// 3. Scrivi "Ciao" e vai a capo
// 4. Scrivi "Mondo" e vai a capo
// 5. Chiudi il file salvando tutto
// 6. Rilascia le risorse

// Il file ora contiene:
// Ciao
// Mondo

Leggere i Dati dai File - StreamReader

πŸ€” Il Problema: I Dati Scompaiono!

Hai imparato a salvare i dati su file con StreamWriter. Ma cosa succede quando chiudi il programma e lo riapri? La lista è vuota! 😒

Per risolvere questo problema, devi imparare a LEGGERE i file e ricaricare i dati!

πŸ”„ Il Ciclo Completo dei Dati

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. INIZIO PROGRAMMA                             β”‚
β”‚    └─→ Leggi file CSV (StreamReader) πŸ“–         β”‚
β”‚        └─→ Riempi List<Automobile>               β”‚
β”‚            └─→ Mostra nella ListBox             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 2. UTENTE LAVORA                                β”‚
β”‚    └─→ Aggiunge auto                            β”‚
β”‚    └─→ Modifica auto                            β”‚
β”‚    └─→ Rimuove auto                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 3. SALVATAGGIO                                  β”‚
β”‚    └─→ Scrivi file CSV (StreamWriter) πŸ’Ύ       β”‚
β”‚        └─→ Salva List<Automobile> su disco      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 4. CHIUDE PROGRAMMA                             β”‚
β”‚    └─→ I dati sono al SICURO nel file!         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 5. RIAPRE PROGRAMMA                             β”‚
β”‚    └─→ Torna al punto 1! πŸ”„                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

StreamReader - I Metodi Base

  1. Controllare se un File Esiste

PRIMA di leggere un file, devi sempre controllare se esiste!

Controllo File.Exists()

using System.IO;  // ← Necessario per File.Exists()

// Controlla se il file esiste
if (File.Exists("automobile.csv"))
{
    // βœ… Il file esiste, puoi leggerlo
    Console.WriteLine("File trovato!");
}
else
{
    // ❌ Il file NON esiste
    MessageBox.Show("File non trovato! Devi salvare prima.");
}
  1. Leggere Tutto il File in Una Volta

Metodo 1: ReadToEnd()

// ═══════════════════════════════════════════════
// Legge TUTTO il contenuto del file
// ═══════════════════════════════════════════════
private void btnLeggiTutto_Click(object sender, EventArgs e)
{
    // STEP 1: Controlla se esiste
    if (!File.Exists("parco_auto.txt"))
    {
        MessageBox.Show("File non trovato!");
        return;
    }

    try
    {
        // STEP 2: Apri il file in LETTURA
        using (StreamReader lettore = new StreamReader("parco_auto.txt"))
        {
            // STEP 3: Leggi TUTTO il contenuto
            string tuttoIlTesto = lettore.ReadToEnd();

            // STEP 4: Mostra il contenuto
            MessageBox.Show(tuttoIlTesto, "Contenuto File");
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Errore: {ex.Message}");
    }
}

πŸ”‘ Metodi di StreamReader

Metodo Cosa Fa
ReadToEnd() Legge TUTTO il file in una stringa
ReadLine() Legge UNA riga alla volta
EndOfStream true se sei arrivato alla fine
  1. Leggere Riga per Riga - Il Metodo Migliore

Metodo 2: ReadLine() in un Ciclo

// ═══════════════════════════════════════════════
// Legge il file riga per riga
// ═══════════════════════════════════════════════
private void btnLeggiRighe_Click(object sender, EventArgs e)
{
    if (!File.Exists("parco_auto.txt"))
    {
        MessageBox.Show("File non trovato!");
        return;
    }

    try
    {
        using (StreamReader lettore = new StreamReader("parco_auto.txt"))
        {
            // Leggi riga per riga finchΓ© non arrivi alla fine
            while (!lettore.EndOfStream)
            {
                // Leggi UNA riga
                string riga = lettore.ReadLine();

                // Elabora la riga (es: mostrala)
                Console.WriteLine(riga);
            }
        }

        MessageBox.Show("File letto con successo!");
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Errore: {ex.Message}");
    }
}

🎬 Come Funziona il Ciclo while

// File contiene 3 righe:
// Riga 1: "Fiat 500 - 1200cc - Benzina"
// Riga 2: "BMW Serie 3 - 2000cc - Diesel"
// Riga 3: "Tesla Model 3 - 0cc - Elettrica"

using (StreamReader lettore = new StreamReader("auto.txt"))
{
    // PRIMA ITERAZIONE:
    lettore.EndOfStream β†’ false (ci sono righe)
    riga = lettore.ReadLine() β†’ "Fiat 500 - 1200cc - Benzina"

    // SECONDA ITERAZIONE:
    lettore.EndOfStream β†’ false
    riga = lettore.ReadLine() β†’ "BMW Serie 3 - 2000cc - Diesel"

    // TERZA ITERAZIONE:
    lettore.EndOfStream β†’ false
    riga = lettore.ReadLine() β†’ "Tesla Model 3 - 0cc - Elettrica"

    // QUARTA ITERAZIONE:
    lettore.EndOfStream β†’ true (FINE!)
    while ESCE dal ciclo
}

Caricare Auto da CSV - Esempio Completo

  1. Pulsante "Carica da CSV"

Questo codice legge il file CSV e ricrea gli oggetti Automobile!

Form1.cs - Caricamento Completo da CSV

// ═══════════════════════════════════════════════
// EVENTO: Carica auto da file CSV
// ═══════════════════════════════════════════════
private void btnCaricaCSV_Click(object sender, EventArgs e)
{
    // STEP 1: Controlla se il file esiste
    if (!File.Exists("automobile.csv"))
    {
        MessageBox.Show("File automobile.csv non trovato!\n" +
                      "Salva prima alcune auto con il pulsante 'Salva CSV'.",
                      "File Non Trovato",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Warning);
        return;
    }

    try
    {
        // STEP 2: Pulisci la lista attuale
        // (rimuovi tutte le auto che ci sono ora)
        listaAuto.Clear();

        int autoCaricate = 0;   // Contatore auto caricate
        int rigaCorrente = 0;   // Numero riga attuale

        // STEP 3: Apri il file in lettura
        using (StreamReader lettore = new StreamReader("automobile.csv"))
        {
            // STEP 4: Salta la prima riga (intestazione)
            // Prima riga: "Modello;Cilindrata;Carburante;Prezzo"
            if (!lettore.EndOfStream)
            {
                string intestazione = lettore.ReadLine();
                rigaCorrente++;
                // Non usiamo questa riga, era solo l'intestazione
            }

            // STEP 5: Leggi tutte le altre righe (i dati veri)
            while (!lettore.EndOfStream)
            {
                rigaCorrente++;
                string riga = lettore.ReadLine();

                // STEP 6: Salta righe vuote
                if (string.IsNullOrWhiteSpace(riga))
                    continue;

                try
                {
                    // STEP 7: Dividi la riga in parti con Split
                    // Es: "Fiat 500;1200;Benzina;15000"
                    string[] parti = riga.Split(';');

                    // STEP 8: Controlla che ci siano esattamente 4 parti
                    if (parti.Length != 4)
                    {
                        MessageBox.Show($"Riga {rigaCorrente} non valida: {riga}",
                                      "Attenzione",
                                      MessageBoxButtons.OK,
                                      MessageBoxIcon.Warning);
                        continue;  // Salta questa riga e vai alla prossima
                    }

                    // STEP 9: Estrai i dati dalle parti
                    string modello = parti[0];               // "Fiat 500"
                    int cilindrata = Convert.ToInt32(parti[1]);      // 1200
                    string carburante = parti[2];            // "Benzina"
                    double prezzo = Convert.ToDouble(parti[3]);      // 15000.0

                    // STEP 10: Crea un nuovo oggetto Automobile
                    Automobile auto = new Automobile(modello, cilindrata,
                                                    carburante, prezzo);

                    // STEP 11: Aggiungi l'auto alla lista
                    listaAuto.Add(auto);
                    autoCaricate++;
                }
                catch (FormatException)
                {
                    // Errore di conversione (es: "ABC" invece di un numero)
                    MessageBox.Show($"Errore riga {rigaCorrente}: dati non validi",
                                  "Errore Formato",
                                  MessageBoxButtons.OK,
                                  MessageBoxIcon.Error);
                }
                catch (Exception ex)
                {
                    // Altri errori imprevisti
                    MessageBox.Show($"Errore riga {rigaCorrente}: {ex.Message}",
                                  "Errore",
                                  MessageBoxButtons.OK,
                                  MessageBoxIcon.Error);
                }
            }
        } // ← Il file si chiude automaticamente qui

        // STEP 12: Aggiorna la visualizzazione
        AggiornaListaAuto();
        AggiornaStatistiche();

        // STEP 13: Mostra messaggio di successo
        MessageBox.Show($"βœ… Caricate {autoCaricate} auto con successo!",
                      "Caricamento Completato",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Information);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"Errore durante il caricamento: {ex.Message}",
                      "Errore",
                      MessageBoxButtons.OK,
                      MessageBoxIcon.Error);
    }
}

πŸ” Split() - Dividere una Stringa

// Riga del CSV (Γ¨ una STRINGA unica):
string riga = "Fiat 500;1200;Benzina;15000";

// Split() la divide in parti usando ';' come separatore
string[] parti = riga.Split(';');

// Risultato - array con 4 elementi:
// parti[0] = "Fiat 500"    ← Modello
// parti[1] = "1200"        ← Cilindrata (stringa!)
// parti[2] = "Benzina"     ← Carburante
// parti[3] = "15000"       ← Prezzo (stringa!)

// Attenzione: parti[1] e parti[3] sono STRINGHE!
// Devi convertirle:
int cilindrata = Convert.ToInt32(parti[1]);    // "1200" β†’ 1200
double prezzo = Convert.ToDouble(parti[3]);    // "15000" β†’ 15000.0

Caricamento Automatico all'Avvio

  1. Caricare i Dati Quando il Programma Si Apre

Il modo migliore è caricare automaticamente i dati nel costruttore del Form! Così l'utente ritrova subito le sue auto. 😊

Form1.cs - Caricamento Automatico nel Costruttore

public partial class Form1 : Form
{
    private List<Automobile> listaAuto;
    private int indiceModifica = -1;

    public Form1()
    {
        InitializeComponent();

        // Inizializza la lista vuota
        listaAuto = new List<Automobile>();

        // Popola la ComboBox con i carburanti
        InizializzaCarburanti();

        // ═══════════════════════════════════════════════
        // CARICA I DATI AUTOMATICAMENTE ALL'AVVIO
        // ═══════════════════════════════════════════════
        CaricaDatiDaFile();
    }

    // ═══════════════════════════════════════════════
    // Metodo per caricare i dati all'avvio
    // ═══════════════════════════════════════════════
    private void CaricaDatiDaFile()
    {
        // Se il file non esiste, esci silenziosamente
        // (Γ¨ la prima volta che usi il programma)
        if (!File.Exists("automobile.csv"))
        {
            return;  // Lista rimane vuota
        }

        try
        {
            using (StreamReader lettore = new StreamReader("automobile.csv"))
            {
                // Salta intestazione
                if (!lettore.EndOfStream)
                {
                    lettore.ReadLine();
                }

                // Carica tutte le auto
                while (!lettore.EndOfStream)
                {
                    string riga = lettore.ReadLine();

                    // Salta righe vuote
                    if (string.IsNullOrWhiteSpace(riga))
                        continue;

                    try
                    {
                        string[] parti = riga.Split(';');

                        // Verifica che ci siano 4 parti
                        if (parti.Length == 4)
                        {
                            string modello = parti[0];
                            int cilindrata = Convert.ToInt32(parti[1]);
                            string carburante = parti[2];
                            double prezzo = Convert.ToDouble(parti[3]);

                            Automobile auto = new Automobile(modello, cilindrata,
                                                            carburante, prezzo);
                            listaAuto.Add(auto);
                        }
                    }
                    catch
                    {
                        // Salta righe con errori (continua con le altre)
                        continue;
                    }
                }
            }

            // Aggiorna la visualizzazione
            AggiornaListaAuto();
            AggiornaStatistiche();
        }
        catch
        {
            // Se c'Γ¨ un errore generale, ignora
            // (lista rimane vuota, non crashare il programma)
        }
    }
}

βœ… Vantaggi del Caricamento Automatico

  • πŸš€ Automatico: L'utente non deve cliccare nessun pulsante
  • πŸ’Ύ Persistenza: I dati sopravvivono alla chiusura del programma
  • πŸ‘€ User-Friendly: Esperienza fluida e professionale
  • πŸ”’ Sicuro: Se il file non esiste o ha errori, non crasha

Gestione Errori - Problemi Comuni

πŸ› Errori Comuni nella Lettura File

1️⃣ Errore: File Non Trovato

// ❌ SBAGLIATO - Non controlli se esiste
StreamReader lettore = new StreamReader("file_che_non_esiste.csv");
// πŸ’₯ CRASH! FileNotFoundException

// βœ… CORRETTO - Controlla sempre prima
if (File.Exists("automobile.csv"))
{
    // OK, il file esiste, puoi leggerlo
    StreamReader lettore = new StreamReader("automobile.csv");
}
else
{
    MessageBox.Show("File non trovato!");
    return;
}

2️⃣ Errore: Formato CSV Sbagliato

// File corrotto:
// "Fiat 500;1200;Benzina"  ← Manca il prezzo!

string[] parti = riga.Split(';');
// parti.Length = 3 (non 4!)

double prezzo = Convert.ToDouble(parti[3]);
// πŸ’₯ CRASH! parti[3] non esiste!

// βœ… SOLUZIONE: Controlla la lunghezza
if (parti.Length != 4)
{
    MessageBox.Show($"Riga non valida: {riga}");
    continue;  // Salta questa riga
}

// Ora Γ¨ sicuro accedere a parti[3]
double prezzo = Convert.ToDouble(parti[3]);

3️⃣ Errore: Conversione Fallita

// File con errore:
// "Fiat 500;ABC;Benzina;15000"  ← "ABC" non Γ¨ un numero!

int cilindrata = Convert.ToInt32("ABC");
// πŸ’₯ CRASH! FormatException

// βœ… SOLUZIONE: Usa try-catch
try
{
    int cilindrata = Convert.ToInt32(parti[1]);
    double prezzo = Convert.ToDouble(parti[3]);

    // Se arrivi qui, le conversioni sono OK
    Automobile auto = new Automobile(modello, cilindrata, carburante, prezzo);
    listaAuto.Add(auto);
}
catch (FormatException)
{
    MessageBox.Show($"Dato non valido nella riga: {riga}");
    continue;  // Salta questa riga, vai alla prossima
}

🎯 Riepilogo - StreamWriter vs StreamReader

Aspetto StreamWriter (Scrittura) StreamReader (Lettura)
Scopo πŸ“ Scrivere dati πŸ“– Leggere dati
Creazione new StreamWriter("file.txt") new StreamReader("file.txt")
Metodi WriteLine() Write() ReadLine() ReadToEnd() EndOfStream
File Esiste? Lo crea se non esiste ❌ Errore se non esiste
Usa File.Exists()
Quando Salvare dati su disco Caricare dati da disco
Esempio Pulsante "Salva" Avvio programma o pulsante "Carica"

πŸ’‘ Best Practice per File I/O

  1. Usa sempre using: Garantisce chiusura automatica del file
  2. Controlla File.Exists(): Prima di leggere, verifica che il file esista
  3. Gestisci gli errori: Usa try-catch per file corrotti o dati non validi
  4. Valida i dati: Controlla lunghezza array, conversioni, campi vuoti
  5. Carica all'avvio: Migliora l'esperienza utente caricando automaticamente nel costruttore
  6. Salva spesso: Dopo ogni modifica importante (aggiungi, modifica, rimuovi)
  7. Salta righe problematiche: Con continue invece di far crashare tutto

Riepilogo: Cosa Hai Imparato

1️⃣ Scrivere su File

StreamWriter dentro un blocco using salva la lista in un file TXT leggibile o in un CSV da aprire con Excel.

2️⃣ Leggere da File

StreamReader legge riga per riga; Split separa i campi e ricrea gli oggetti Automobile.

3️⃣ Programma Robusto

File.Exists() prima di leggere, try-catch per i file rovinati, continue per saltare le righe sbagliate, caricamento automatico all'avvio.

Esercizi per Fare Pratica

Riprendi i progetti della lezione precedente e aggiungi:

  1. Gestionale Contatti: salva i contatti in un file TXT e ricaricali all'avvio.
  2. Registro Voti: salva tutto in CSV (Nome;Materia;Voto) e prova ad aprirlo con Excel.
  3. Catalogo Libri: salva la biblioteca in un TXT ben formattato; se una riga del file Γ¨ sbagliata, saltala senza far bloccare il programma.

🧬 Nella prossima lezione il Parco Auto si allarga: auto elettriche e sportive con l'ereditarietà.

πŸ“š Teoria collegata (percorso C# – il linguaggio, esempi in console): Lettura e scrittura dei file e Gestione delle eccezioni.