CodeGym /Corsi /JAVA 25 SELF /Verifica dell'esistenza di file e directory

Verifica dell'esistenza di file e directory

JAVA 25 SELF
Livello 38 , Lezione 1
Disponibile

1. Metodi per verificare l'esistenza di file e directory

Lavorare con i file a volte ricorda una passeggiata in un campo minato: non sai mai cosa ti aspetta dietro il prossimo byte. La buona notizia: Java ci dà un «metal detector» — metodi per verificare l'esistenza di file e cartelle.

Classe File: verifica tramite exists(), isFile(), isDirectory()

Il modo classico è usare la classe java.io.File:

File file = new File("example.txt");
if (file.exists()) {
    System.out.println("Il file esiste!");
} else {
    System.out.println("File non trovato.");
}

Il metodo exists() restituisce true se esiste un file o una cartella con quel nome. Ma non è tutto! A volte serve sapere cosa esattamente esiste: un file o una directory.

if (file.isFile()) {
    System.out.println("È un file.");
} else if (file.isDirectory()) {
    System.out.println("È una cartella.");
} else {
    System.out.println("Non è stato trovato nulla.");
}

Classi Path e Files: approccio moderno

Nelle applicazioni moderne è meglio usare l'API più recente e potente java.nio.file. Qui per verificare l'esistenza si usa il metodo statico Files.exists():

import java.nio.file.*;

Path path = Paths.get("example.txt");
if (Files.exists(path)) {
    System.out.println("File trovato con NIO!");
}

Per verificare il tipo dell'oggetto usate:

if (Files.isRegularFile(path)) {
    System.out.println("È un file regolare!");
}
if (Files.isDirectory(path)) {
    System.out.println("È una directory!");
}

Consiglio: per i nuovi progetti è meglio usare subito NIO (Path, Files), perché questo API è più moderno, supporta più funzionalità ed è amico di try-with-resources.

Tabella: confronto degli approcci

Approccio Verifica dell'esistenza Verifica del tipo (file/cartella) Attualità
File.exists()
Sì (isFile(), isDirectory()) Vecchio
Files.exists(Path)
Sì (isRegularFile(), isDirectory()) Consigliato

2. Problema TOCTOU: perché la verifica — non è una panacea

In che cosa consiste il problema?

Supponiamo che abbiate verificato: «Il file esiste!» — e subito dopo decidiate di leggerlo. Ma tra queste due azioni può passare un'eternità in termini di CPU. In quel lasso di tempo il file può essere eliminato, spostato, sostituito da un altro processo, oppure i suoi permessi possono cambiare.

È come guardare nel frigorifero, notare che c'è una torta, chiudere lo sportello e poi riaprirlo — per scoprire che la torta è già stata mangiata. Anche in programmazione esistono questi «coinquilini»: altri processi, utenti, antivirus, il file system stesso.

Perché è importante?

Di conseguenza, anche se avete verificato che il file esiste, al momento di aprirlo può comunque verificarsi un'eccezione — ad esempio, FileNotFoundException o AccessDeniedException.

Quindi la verifica — non è una garanzia, ma solo una protezione aggiuntiva. Siate sempre pronti alle eccezioni e gestitele!

3. Pratica: verifichiamo l'esistenza del file prima della lettura

Aggiungiamo una funzione che stampa il contenuto del file se esiste e informa l'utente se il file non c'è. Mostreremo due varianti: tramite l'API vecchio e quello nuovo.

Variante 1: tramite File

import java.io.*;

public class FileExistenceCheck {
    public static void main(String[] args) {
        File file = new File("notes.txt");
        if (file.exists() && file.isFile()) {
            try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                System.out.println("Errore durante la lettura del file: " + e.getMessage());
            }
        } else {
            System.out.println("File 'notes.txt' non trovato.");
        }
    }
}

Variante 2: tramite Path e Files

import java.nio.file.*;
import java.io.IOException;

public class PathExistenceCheck {
    public static void main(String[] args) {
        Path path = Paths.get("notes.txt");
        if (Files.exists(path) && Files.isRegularFile(path)) {
            try {
                Files.lines(path).forEach(System.out::println);
            } catch (IOException e) {
                System.out.println("Errore durante la lettura del file: " + e.getMessage());
            }
        } else {
            System.out.println("File 'notes.txt' non trovato.");
        }
    }
}

Anche dopo la verifica — intercettiamo le eccezioni!

In entrambi gli esempi, nonostante il controllo preliminare, usiamo comunque blocchi trycatch, perché il file può scomparire o diventare inaccessibile in qualsiasi momento. Questa è la regola d'oro nel lavoro con i file!

4. Verifica dell'esistenza di una directory

In modo analogo si può verificare l'esistenza di una cartella e, se assente, crearla:

import java.nio.file.*;

public class DirectoryCheck {
    public static void main(String[] args) {
        Path dir = Paths.get("data");
        if (Files.exists(dir) && Files.isDirectory(dir)) {
            System.out.println("Cartella 'data' trovata.");
        } else {
            System.out.println("Cartella 'data' non trovata. La creiamo...");
            try {
                Files.createDirectory(dir);
                System.out.println("Cartella creata!");
            } catch (IOException e) {
                System.out.println("Errore durante la creazione della cartella: " + e.getMessage());
            }
        }
    }
}

A proposito:
Il metodo Files.createDirectory() genera un'eccezione se la cartella esiste già. Se volete creare una catena di cartelle (ad esempio, "data/2025/09"), usate Files.createDirectories(), che non si lamenta se una parte delle cartelle esiste già.

5. Particolarità e sfumature: percorsi relativi e assoluti

Percorsi relativi

Quando scrivete "notes.txt", il programma cerca il file nella «directory di lavoro corrente». La sua posizione dipende da come e da dove avviate l'applicazione (IDE, terminale, doppio clic sul JAR, ecc.).

Percorsi assoluti

Se volete essere sicuri di dove cercare, è meglio usare percorsi assoluti oppure costruirli dinamicamente:

String userHome = System.getProperty("user.home");
Path filePath = Paths.get(userHome, "myapp", "notes.txt");

Verifica del tipo di oggetto

A volte il «file» può rivelarsi inaspettatamente una directory. Quindi controllate non solo l'esistenza, ma anche il tipo:

if (Files.isRegularFile(path)) {
    // È proprio un file!
}
if (Files.isDirectory(path)) {
    // È una cartella!
}

6. Dimostrazione pratica del problema TOCTOU

Simuliamo una situazione in cui il file scompare dopo il controllo ma prima dell'apertura. Eseguite il codice ed eliminate manualmente il file tra il controllo e la lettura:

import java.io.*;
import java.nio.file.*;

public class TOCTOUExample {
    public static void main(String[] args) {
        Path path = Paths.get("notes.txt");
        if (Files.exists(path)) {
            System.out.println("File trovato, ora leggeremo...");
            // A questo punto aprite il file manager ed eliminate manualmente il file "notes.txt"!
            try {
                Files.lines(path).forEach(System.out::println);
            } catch (IOException e) {
                System.out.println("Ops! Il file è scomparso: " + e.getMessage());
            }
        } else {
            System.out.println("File non trovato.");
        }
    }
}

Risultato:
Se riuscite a eliminare il file tra il controllo e la lettura, otterrete un'eccezione. Questo mostra chiaramente che anche un controllo scrupoloso non salva da cambiamenti imprevisti.

7. Errori tipici nella verifica dell'esistenza di file e cartelle

Errore №1: Affidarsi solo al controllo senza usare try-catch. Se «il file c'è», allora si può leggerlo tranquillamente — pensano i principianti. Ma il file può scomparire o diventare inaccessibile e il programma può andare in crash.

Errore №2: Verificare solo l'esistenza senza controllare il tipo. Se controllate solo exists() senza specificare se sia un file o una cartella, potreste provare ad aprire una cartella come se fosse un file — e ottenere un errore.

Errore №3: Usare percorsi relativi senza capire la directory di lavoro. Il programma cerca il file «nel posto sbagliato» e l'utente non capisce perché nulla funzioni.

Errore №4: Non considerare i permessi di accesso. Il file o la cartella possono esistere, ma mancare i permessi di lettura/scrittura. Questi errori emergono solo al momento dell'apertura del file — usate sempre trycatch.

Errore №5: Ignorare la sensibilità al maiuscolo/minuscolo del nome file sui diversi sistemi operativi. In Windows i nomi dei file non sono sensibili al maiuscolo/minuscolo, in Linux lo sono. Il programma potrebbe non trovare "Notes.txt", se cerca "notes.txt".

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