CodeGym /Corsi /C# SELF /Scrittura di file di testo:

Scrittura di file di testo: StreamWriter

C# SELF
Livello 36 , Lezione 3
Disponibile

1. Introduzione

StreamWriter è una delle classi chiave dello spazio dei nomi System.IO in .NET, pensata per scrivere facilmente dati di testo su file tramite stream.

Perché non lavorare direttamente con FileStream?
FileStream lavora solo con byte. Se provi a scrivere una stringa con lui, devi convertire il testo in byte da solo e preoccuparti della codifica (fidati, dopo un po' vorrai tornare a StreamWriter).
StreamWriter invece si occupa di tutto questo: gli dai una stringa e lui scrive i byte giusti nel file.

I vantaggi principali:

  • Scrivi stringhe senza pensare alla conversione in byte.
  • Ha metodi per scrivere testo riga per riga.
  • Gestione del buffering e della codifica (e impareremo anche a usarli).

Esempio base

using System.IO;

string path = "output.txt";

using (StreamWriter writer = new StreamWriter(path))
{
    writer.WriteLine("Ciao, mondo!");
    writer.WriteLine("Questa è la seconda riga.");
}
// Dopo l'uscita dalle parentesi graffe di using, StreamWriter libera sicuramente il file.

Cosa succede qui?

  • Si apre il file per la scrittura (se il file non esiste, viene creato).
  • Ogni stringa viene scritta come una riga separata nel file (metodo WriteLine).
  • Dopo il blocco using il file viene chiuso automaticamente, anche se ci sono errori.

Se apri il file output.txt dopo aver eseguito questo programma, vedrai due righe di testo, proprio come previsto.

Nota importante

Se il file esiste già, verrà sovrascritto da zero! Tutto quello che c'era dentro — sparisce. Quindi occhio: non salvare in questi file la tua tesi o l'unica ricevuta delle bollette.

2. Scrittura di dati nello stream

I metodi principali di StreamWriter

Metodo Descrizione
Write(string)
Scrive una stringa senza andare a capo
WriteLine(string)
Scrive una stringa e va a capo
Flush()
Forza la scrittura del buffer su file (da fare raramente a mano)
Close()
/
Dispose()
Chiude lo stream e libera la risorsa (lo fa using)
BaseStream
Accedi allo stream di base (tipo FileStream)

Metodo Write()

Scrive dati senza andare a capo. Tutto quello che scrivi dopo sarà sulla stessa riga del file.

Metodo WriteLine()

Scrive dati aggiungendo automaticamente il carattere di fine riga (\r\n su Windows, \n su sistemi Unix-like).
È come premere Invio dopo ogni scrittura.

Write() vs WriteLine(): dimostrazione della differenza

using (var writer = new StreamWriter("example.txt"))
{
    writer.Write("Primo ");
    writer.Write("paragrafo. ");
    writer.WriteLine("Abbiamo finito la riga, Invio!");
    writer.Write("Secondo paragrafo.");
}

Ora example.txt sarà più o meno così:

Primo paragrafo. Abbiamo finito la riga, Invio!
Secondo paragrafo.

3. Lavorare con le codifiche

Di default, se crei uno StreamWriter senza parametri, viene usata la codifica UTF-8 con BOM (Byte Order Mark).

Nella pratica è comodo e moderno, ma a volte serve specificare la codifica — tipo per compatibilità con vecchi programmi o dati importati.

Come specificare la codifica?

// Scrittura di un file in codifica Windows-1251 (cirillico per vecchi sistemi)
using (var writer = new StreamWriter("cyrillic.txt", false, System.Text.Encoding.GetEncoding("windows-1251")))
{
    writer.WriteLine("Ciao, mondo cirillico!");
}

Nota importante:
La codifica deve essere supportata dal sistema. Se non sei sicuro — usa UTF-8.

4. Parametri extra del costruttore

Diamo un'occhiata sotto il cofano di StreamWriter:

public StreamWriter(
    string path,              // percorso del file
    bool append = false,      // aggiungere in fondo al file?
    Encoding encoding = null, // codifica
    int bufferSize = 1024     // dimensione buffer, byte
)
  • append — se false (default), il file viene sovrascritto. Se true, le nuove scritte vanno in fondo.
  • encoding — la codifica usata.
  • bufferSize — dimensione del buffer interno per lavorare più veloce con tanti dati.

Esempio: aggiungere allo stesso file

// Il file verrà aggiornato, non sovrascritto
using (var writer = new StreamWriter("log.txt", append: true))
{
    writer.WriteLine(DateTime.Now + " -- Nuovo evento");
}

5. Consigli utili

Cosa succede con aggiunta e sovrascrittura

Modalità Cosa fa? Risultato nel file
append: false Sovrascrive tutto da zero I vecchi dati vengono cancellati
append: true Aggiunge nuove righe in fondo Le vecchie righe restano

Tip: La modalità aggiunta (append: true) è perfetta per i log, quando vuoi tenere la cronologia degli eventi.

StreamWriter e grandi quantità di dati

  • StreamWriter fa buffering: i dati reali finiscono nel file un po' dopo che chiami WriteLine. Ma dopo che chiudi lo stream (o chiami Flush()) tutto è sicuramente su disco.
  • Scrivere con WriteLine è super efficiente per output riga per riga. Per formati complessi (JSON, CSV o XML) meglio usare le librerie giuste, oppure fare attenzione a gestire i caratteri speciali (tipo virgole o virgolette).

Come chiudere correttamente e liberare risorse

Il modo giusto: usa sempre using!
Così sei sicuro che il file viene chiuso anche se succede un'eccezione (tipo se il disco "finisce" o il file viene bloccato da un altro programma).


flowchart TD
    A[Creazione StreamWriter] --> B[Lavoro con il file]
    B --> C{Eccezione?}
    C -- Sì --> D[Viene chiamato Dispose]
    C -- No --> D
    D --> E[File sicuramente chiuso]
Schema: using garantisce la chiusura del file anche in caso di errori

6. Esempi pratici

Supponiamo che nel corso abbiamo una mini-app per gestire libri. Aggiungiamo la funzionalità per salvare nuovi libri su file.

Esempio: Salviamo un nuovo libro in un file separato

using System;
using System.IO;

class Program
{
    static void Main()
    {
        Console.WriteLine("Inserisci il titolo del libro:");
        string bookTitle = Console.ReadLine();

        Console.WriteLine("Inserisci l'autore:");
        string author = Console.ReadLine();

        string path = "books.txt";
        using (var writer = new StreamWriter(path, append: true))
        {
            writer.WriteLine($"{bookTitle};{author}");
            // Formato CSV: ogni riga è un libro, separato da punto e virgola
        }

        Console.WriteLine("Libro salvato nel file!");
    }
}

Prova ad aggiungere più libri di fila. Nel file books.txt le righe verranno aggiunte senza cancellare le precedenti. Questo è comodo per log o registri — tipo per il tuo futuro sistema di audit quando diventerai uno sviluppatore Enterprise.

7. Come evitare errori tipici quando scrivi su file

La maggior parte dei principianti si trova davanti a questi problemi:

File non chiuso e bloccato da un altro processo. Motivo — ti sei dimenticato using.

Hai scritto tante righe ma il file è vuoto: ti sei dimenticato di chiamare Flush() o di chiudere lo stream (ma con using succede in automatico).

Hai sovrascritto il file invece di aggiungere — ti sei dimenticato append: true.

Problemi di codifica: il file si apre con "caratteri strani" in Blocco Note — hai scelto la codifica sbagliata o l'altro programma non supporta UTF-8.

Eccezioni UnauthorizedAccessException o DirectoryNotFoundException: il programma prova a salvare il file dove non ha i permessi, o in una cartella che non esiste. Controlla percorso e permessi.

Errore "file is used by another process": hai aperto il file in scrittura ma non l'hai chiuso, o qualcun altro sta scrivendo nello stesso file.

Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION