1. Creazione delle directory
La directory (ossia cartella) non è solo un contenitore per file, ma la base dell’organizzazione dei dati sul disco. Nelle applicazioni creiamo continuamente cartelle per dati di input/output, log, file temporanei ecc. Le API moderne di java.nio.file lo rendono comodo e multipiattaforma.
Vediamo come creare, eliminare e visualizzare il contenuto delle cartelle usando le classi Files, Path e Paths.
Files.createDirectory(path)
Crea una directory nel percorso indicato. Se la directory padre è assente — verrà lanciata un’eccezione.
import java.nio.file.*;
public class DirectoryDemo {
public static void main(String[] args) throws Exception {
Path dir = Paths.get("testDir");
if (!Files.exists(dir)) {
Files.createDirectory(dir);
System.out.println("Directory creata: " + dir.toAbsolutePath());
} else {
System.out.println("La directory esiste già: " + dir.toAbsolutePath());
}
}
}
Se provi a creare una directory che esiste già, otterrai FileAlreadyExistsException.
Files.createDirectories(path)
Crea l’intera catena di directory. Se una delle directory intermedie manca — verrà creata automaticamente. Se parte della catena esiste già — non ci sarà alcun errore.
Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("Catena di directory creata: " + nestedDir.toAbsolutePath());
È come chiedere a Java di costruire non solo la casa, ma anche l’ingresso e la strada, se non esistono ancora.
Esempio tipico: creiamo la struttura per un progetto
Supponiamo di dover salvare i report nella cartella output/reports/2024. Non controllare ogni directory manualmente — usa createDirectories.
Path reportsPath = Paths.get("output/reports/2024");
Files.createDirectories(reportsPath);
Java capirà da sola cosa esiste già e cosa va creato.
2. Eliminazione di file e directory
Files.delete(path)
Elimina un file o una directory vuota. Se la directory non è vuota — verrà lanciata DirectoryNotEmptyException.
Path dir = Paths.get("testDir");
try {
Files.delete(dir);
System.out.println("Directory eliminata: " + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
System.out.println("Impossibile eliminare: la directory non è vuota!");
}
Files.deleteIfExists(path)
Funziona come delete, ma non lancia un errore se l’oggetto non esiste. Restituisce true se qualcosa è stato eliminato, e false — se l’oggetto non c’era.
Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
System.out.println("File eliminato.");
} else {
System.out.println("File non trovato, non è stato eliminato nulla.");
}
Come eliminare una directory non vuota?
Non è possibile eliminare direttamente una cartella non vuota. Prima bisogna eliminare tutto il suo contenuto (file e sottodirectory), e poi la cartella stessa. Si fa in modo ricorsivo, ad esempio tramite Files.walkFileTree:
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
public class DeleteDirectoryRecursively {
public static void main(String[] args) throws IOException {
Path dir = Paths.get("parent");
if (Files.exists(dir)) {
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
System.out.println("La directory e tutto il suo contenuto sono stati eliminati.");
}
}
}
Se stai iniziando, non spaventarti di questo codice — più avanti analizzeremo walkFileTree in dettaglio.
3. Visualizzare il contenuto di una directory
Files.list(path)
Restituisce Stream<Path> — uno stream di percorsi. Puoi elaborare il contenuto della cartella tramite lo Stream API. Ogni elemento è un file o una sottodirectory (senza ricorsione!).
Path dir = Paths.get("output/reports");
if (Files.exists(dir) && Files.isDirectory(dir)) {
try (var stream = Files.list(dir)) {
stream.forEach(path -> System.out.println(path.getFileName()));
}
}
Dettaglio importante: lo stream va chiuso, quindi usiamo il try‑with‑resources.
Esempio: stampiamo i nomi dei file e delle sottodirectory
Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
stream.forEach(path -> {
String type = Files.isDirectory(path) ? "directory" : "file";
System.out.println(path.getFileName() + " — " + type);
});
}
Ottenere l’elenco dei file come collezione
List<Path> files = Files.list(reports2024)
.filter(Files::isRegularFile)
.toList();
System.out.println("File nella cartella:");
files.forEach(System.out::println);
Importante: Files.list(path) restituisce solo il contenuto della directory corrente (livello superiore). Per l’attraversamento ricorsivo usa Files.walk(path).
4. Pratica: mini file manager
L’utility crea la directory mydata/logs, il file log1.txt, stampa il contenuto della cartella e poi elimina tutto.
import java.nio.file.*;
import java.io.IOException;
public class MiniFileManager {
public static void main(String[] args) throws IOException {
Path logsDir = Paths.get("mydata/logs");
Files.createDirectories(logsDir);
Path logFile = logsDir.resolve("log1.txt");
Files.writeString(logFile, "Ciao, log!");
System.out.println("Contenuto della cartella " + logsDir + ":");
try (var stream = Files.list(logsDir)) {
stream.forEach(path -> System.out.println(" - " + path.getFileName()));
}
Files.deleteIfExists(logFile);
Files.deleteIfExists(logsDir);
System.out.println("File e cartella eliminati.");
}
}
Commenti al codice:
- Files.createDirectories garantisce la creazione dell’intera catena.
- resolve — un modo comodo per aggiungere al percorso il nome di un file.
- Chiudiamo lo stream di Files.list con try‑with‑resources — particolarmente critico su Windows.
5. Particolarità e dettagli
Verifica dell’esistenza
Prima di creare/eliminare è utile verificare se il percorso esiste:
if (!Files.exists(path)) {
Files.createDirectory(path);
}
Permessi di accesso
Se il programma non ha i permessi per creare/eliminare — otterrai AccessDeniedException. Ad esempio, creare una cartella nella radice del disco come utente normale quasi sempre terminerà con un errore.
Directory vuota e non vuota
Si può eliminare solo una directory vuota (Files.delete). Per eliminare con tutto il contenuto usa un attraversamento ricorsivo (walkFileTree).
Multipiattaforma
L’API java.nio.file funziona correttamente su tutti i sistemi operativi più diffusi e tiene conto dei separatori di percorso. Per costruire i percorsi usa Paths.get e Path.resolve, non concatenare stringhe.
Collegamenti simbolici
Nei casi di base puoi non pensarci, ma se trovi voci «insolite» che non sono né un file normale né una directory — potrebbero essere symlink. Ci torneremo nelle lezioni avanzate.
6. Errori tipici nel lavoro con le directory
Errore n. 1: tentativo di eliminare una directory non vuota con una semplice chiamata Files.delete(path). Java lancerà DirectoryNotEmptyException. Prima elimina il contenuto, poi la cartella stessa.
Errore n. 2: dimenticare di chiudere lo stream da Files.list(). Se non usi il try‑with‑resources, lo stream rimarrà aperto e su Windows è possibile un errore durante l’eliminazione della cartella.
Errore n. 3: creazione di una directory senza controllare la presenza del genitore. La chiamata a Files.createDirectory per un percorso del tipo parent/child, quando parent non esiste, porterà a NoSuchFileException. Usa Files.createDirectories.
Errore n. 4: uso di percorsi assoluti senza necessità. Preferisci percorsi relativi all’interno del progetto — il codice sarà più portabile.
Errore n. 5: IOException non gestita. Qualsiasi operazione con il file system può terminare con un errore. Incapsula in try-catch oppure ripropaga l’eccezione verso l’alto.
Errore n. 6: tentativo di creare/eliminare in una cartella a cui non hai permessi. In questo caso otterrai AccessDeniedException. Verifica il contesto di esecuzione e i permessi di accesso.
GO TO FULL VERSION