CodeGym /Corsi /C# SELF /Classi statiche File

Classi statiche File e Directory

C# SELF
Livello 39 , Lezione 0
Disponibile

1. Introduzione

Lavorare direttamente con gli stream (StreamReader, StreamWriter, FileStream) è molto utile, soprattutto quando hai bisogno di controllare la lettura/scrittura a basso livello: per esempio scrivere blocchi "a pezzi" o processare file grandi a parti.

Ma nella vita reale spesso serve semplicemente sapere: "esiste questo file?", "copiare un file da una posizione a un'altra", "cancellare un file", "ottenere la lista di tutti i file .txt in una cartella", e così via. Per questi casi Microsoft ha creato due utility universali: le classi statiche File e Directory. Statiche significa che non devi creare un'istanza: chiami direttamente il metodo sul nome della classe.

Analogia pratica

Se gli stream sono te con una matita che scrive ogni lettera sul foglio, allora File e Directory sono la tua scrivania con i cassetti: puoi "aprire" istantaneamente un cassetto (Directory), tirarne fuori un foglio (File.ReadAllText), buttare via il foglio (File.Delete) o perfino prendere un intero cassetto e spostarlo dall'altra parte della stanza (Directory.Move). Compiti semplici — metodi semplici.

2. Classe File: cos'è e a cosa serve

La classe File offre un set comodo di metodi statici per le operazioni più comuni sui file.

I metodi più usati

Metodo Descrizione
File.Exists(path)
Controlla se esiste un file al percorso
File.ReadAllText(path)
Legge l'intero file come testo
File.ReadAllLines(path)
Legge tutte le righe del file in un array
File.WriteAllText(path, text)
Sovrascrive il file scrivendo il testo
File.AppendAllText(path, text)
Aggiunge testo alla fine del file
File.Copy(source, destination)
Copia un file
File.Delete(path)
Elimina un file
File.Move(source, destination)
Sposta o rinomina un file
File.Open/Read/Write/Create
Apre uno stream per operazioni avanzate

Esempio rapido: controlliamo un file e lo leggiamo

string filePath = "data.txt";

if (File.Exists(filePath))
{
    string content = File.ReadAllText(filePath);
    Console.WriteLine("Contenuto del file:");
    Console.WriteLine(content);
}
else
{
    Console.WriteLine("File non trovato!");
}

Vedi? Nessuna gestione manuale degli stream per il caso semplice!

3. Classe Directory: gestire le cartelle senza dolore

Se File è per i singoli file, allora Directory è per le cartelle (directory).

Compiti principali

Metodo Descrizione
Directory.Exists(path)
Controlla se la cartella esiste
Directory.CreateDirectory(path)
Crea la cartella (o l'intero percorso con le cartelle intermedie)
Directory.Delete(path)
Elimina la cartella (può includere sottodirectory)
Directory.GetFiles(path)
Ottiene la lista dei file nella cartella
Directory.GetDirectories(path)
Ottiene la lista delle sottodirectory
Directory.Move(source, destination)
Sposta o rinomina la cartella
Directory.GetCurrentDirectory()
Ottiene la directory di lavoro corrente dell'applicazione

Esempio: creiamo una cartella e salviamo lì un file

string dirPath = "Results";
if (!Directory.Exists(dirPath))
{
    Directory.CreateDirectory(dirPath);
    Console.WriteLine("Cartella 'Results' creata.");
}

string filePath = Path.Combine(dirPath, "summary.txt");
File.WriteAllText(filePath, "Dati finali: ...");

Console.WriteLine($"File {filePath} scritto.");

4. Scenari tipici d'uso di File e Directory

I metodi base possono sembrare noiosi finché non li vedi all'opera! Vediamo come usare queste classi per risolvere problemi reali e, nel frattempo, continuiamo lo sviluppo della nostra app di esempio (immaginiamo una semplice todo-list che salva i risultati su file).

Salvare i dati su file (sostituendo il file precedente)

// Salviamo la lista di task su file
string[] todos = { "Comprare il pane", "Chiamare il medico", "Fare i compiti di C#" };
string filePath = "todo.txt";
File.WriteAllLines(filePath, todos);

Console.WriteLine("Lista delle cose da fare salvata.");

Caricare i dati dal file

// Carichiamo i task, se il file esiste
if (File.Exists(filePath))
{
    string[] loadedTodos = File.ReadAllLines(filePath);
    Console.WriteLine("La tua lista di cose da fare:");
    foreach (var task in loadedTodos)
    {
        Console.WriteLine("- " + task);
    }
}
else
{
    Console.WriteLine("Non hai ancora una lista di cose da fare.");
}

Aggiungere un nuovo task (senza sovrascrivere il file)

string newTask = "Portare a passeggio il cane";
File.AppendAllText(filePath, newTask + Environment.NewLine);
Console.WriteLine("Task aggiunto!");

Copiare e fare un backup del file

string backupPath = "todo_backup.txt";
File.Copy(filePath, backupPath, overwrite: true);
Console.WriteLine("Backup della lista delle cose da fare creato.");

Spostare (o rinominare) il file

string archivePath = "todo_archive.txt";
File.Move(filePath, archivePath);
Console.WriteLine("Lista delle cose da fare archiviata (rinominata).");

Cancellare il file

if (File.Exists(archivePath))
{
    File.Delete(archivePath);
    Console.WriteLine("Archivio eliminato — liberiamo spazio!");
}

5. Lavorare con le cartelle: esempi

Creare una gerarchia di directory

string path = Path.Combine("Reports", "2024", "June");
Directory.CreateDirectory(path);
Console.WriteLine($"Cartella {path} creata (incluse le cartelle intermedie).");

Ottenere la lista di file e cartelle

string dirPath = "Reports";
if (Directory.Exists(dirPath))
{
    string[] files = Directory.GetFiles(dirPath);
    Console.WriteLine("File nella cartella:");
    foreach (var file in files)
    {
        Console.WriteLine(file);
    }

    string[] subDirs = Directory.GetDirectories(dirPath);
    Console.WriteLine("Sottodirectory:");
    foreach (var dir in subDirs)
    {
        Console.WriteLine(dir);
    }
}

Filtrare i file per pattern (solo txt)

string[] txtFiles = Directory.GetFiles(dirPath, "*.txt");
Console.WriteLine("Solo file .txt:");
foreach (var file in txtFiles)
{
    Console.WriteLine(file);
}

Scansione ricorsiva (file in tutte le sottocartelle)

string[] allFiles = Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories);
Console.WriteLine("File in tutte le cartelle annidate:");
foreach (var file in allFiles)
{
    Console.WriteLine(file);
}

Spostare ed eliminare directory

string from = "OldReports";
string to = "Archive/OldReports";
if (Directory.Exists(from))
{
    Directory.Move(from, to);
    Console.WriteLine($"Cartella {from} spostata in {to}");
}

if (Directory.Exists(to))
{
    Directory.Delete(to, recursive: true); // true: cancellare tutto dentro
    Console.WriteLine($"Cartella {to} eliminata (con tutto il contenuto).");
}

6. Note utili

Integrazione con i percorsi: la classe Path

Quando lavori con file e cartelle spesso devi costruire percorsi completi, unire nomi di directory e file, estrarre estensioni, verificare caratteri validi. Per questo si usa la classe helper Path.

Esempi

string folder = "Results";
string filename = "week1.txt";
string fullPath = Path.Combine(folder, filename); // unione sicura!
Console.WriteLine(fullPath); // "Results/week1.txt" (o "\" su Windows)
  • Ottenere l'estensione del file: Path.GetExtension(fullPath)
  • Ottenere il nome del file senza il percorso: Path.GetFileName(fullPath)

Usa Path.Combine invece di concatenare stringhe — è più sicuro per applicazioni cross-platform.

Metodi "tutto in una volta" vs variante a stream

Molti metodi di File e Directory (per esempio File.ReadAllText, File.WriteAllText, Directory.GetFiles) fanno il lavoro "tutto in una volta": leggono/scrivono/ottengono la lista in una singola operazione. Questo è MOLTO comodo, ma non è adatto per file o directory enormi dove la memoria può finire. Se lavori con gigabyte — passa agli stream (StreamReader, StreamWriter, FileStream, ecc.) o processa i file a pezzi.

Quando usare File/Directory e quando le classi degli stream

Situazione Cosa usare
Devi verificare se esiste un file/cartella
File.Exists, Directory.Exists
Leggere/scrivere un file piccolo tutto insieme
File.ReadAllText, WriteAllText
Aggiungere testo alla fine del file
File.AppendAllText
Ottenere la lista di file in una directory
Directory.GetFiles
Copiare, eliminare, spostare un file
File.Copy/Delete/Move
Copiare/eliminare un'intera cartella Directory.Delete/Move/Copy (Copy — con libreria esterna)
Processare FILE MOLTO grandi a pezzi Classi a stream (StreamReader, FileStream)

Valore pratico e applicazioni reali

  • Caricamento/salvataggio rapido di configurazioni, impostazioni, file JSON/XML.
  • Sistemi di logging (scrittura di log su disco).
  • Utility semplici di backup e migrazione dati.
  • Scansione di cartelle multimedia, foto, documenti.
  • Scenari utente: caricamento template, export/import, generazione report ecc.

Anche nelle interviste tecniche spesso ti chiedono di usare proprio queste classi: "Implementa una funzione che calcola la dimensione totale di tutti i file .txt in una directory", "Fai il backup di file in una cartella separata" e simili.

Cheat-sheet visivo: quale metodo usare

graph TD
    A[Che vuoi fare?]
    A -->|Verificare esistenza| B[File.Exists o Directory.Exists]
    A -->|Leggere/scrivere file completamente| C[File.ReadAllText/WriteAllText]
    A -->|Aggiungere dati a un file| D[File.AppendAllText]
    A -->|Lavorare con cartelle| E[Directory.CreateDirectory, GetFiles, GetDirectories]
    A -->|Copiare/eliminare/spostare file| F[File.Copy/Delete/Move]
    A -->|Copiare/eliminare cartella intera| G[Directory.Delete/Move]

7. Caratteristiche e errori tipici

Controllo dell'esistenza e "race condition". Anche se verifichi che il file/cartella esiste, tra quel controllo e l'operazione reale un altro processo potrebbe cambiarne lo stato. Perciò usa sempre try-catch anche se hai già verificato!

Permessi di accesso. Se l'app non ha permessi di lettura/scrittura/cancellazione, i metodi lanceranno UnauthorizedAccessException.

Percorso troppo lungo. La lunghezza massima del percorso (di solito 260 caratteri su vecchi Windows; in .NET 9 le limitazioni sono più morbide, ma stai comunque attento).

Gestione delle eccezioni. Metodi come File.ReadAllText o Directory.GetFiles non perdonano errori: se il file/cartella non esiste — lanciano subito un'eccezione. Avvolgi in try-catch oppure verifica prima l'esistenza.

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