CodeGym /Kursy /JAVA 25 SELF /Praca z katalogami: tworzenie, usuwanie, przeglądanie zaw...

Praca z katalogami: tworzenie, usuwanie, przeglądanie zawartości

JAVA 25 SELF
Poziom 35 , Lekcja 4
Dostępny

1. Tworzenie katalogów

Katalog (czyli folder) — to nie tylko kontener na pliki, lecz podstawa organizacji danych na dysku. W aplikacjach stale tworzymy katalogi dla danych wejściowych/wyjściowych, logów, plików tymczasowych itd. Nowoczesne API java.nio.file robi to wygodnie i wieloplatformowo.

Zobaczmy, jak tworzyć, usuwać i przeglądać zawartość folderów za pomocą klas Files, Path i Paths.

Files.createDirectory(path)

Tworzy jeden katalog pod wskazaną ścieżką. Jeśli katalog nadrzędny nie istnieje — zostanie rzucony wyjątek.

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("Utworzono katalog: " + dir.toAbsolutePath());
        } else {
            System.out.println("Katalog już istnieje: " + dir.toAbsolutePath());
        }
    }
}

Jeśli spróbujesz utworzyć katalog, który już istnieje, otrzymasz FileAlreadyExistsException.

Files.createDirectories(path)

Tworzy cały łańcuch katalogów. Jeśli któregoś z katalogów pośrednich brakuje — zostanie utworzony automatycznie. Jeśli część łańcucha już istnieje — błąd nie wystąpi.

Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("Utworzono łańcuch katalogów: " + nestedDir.toAbsolutePath());

To tak, jakbyś poprosił Javę, aby zbudowała nie tylko dom, ale także klatkę schodową i ulicę, jeśli jeszcze ich nie było.

Typowy przykład: tworzymy strukturę dla projektu

Załóżmy, że trzeba zapisywać raporty do folderu output/reports/2024. Nie sprawdzaj każdego katalogu ręcznie — użyj createDirectories.

Path reportsPath = Paths.get("output/reports/2024");
Files.createDirectories(reportsPath);

Java sama ustali, co już istnieje, a co należy utworzyć.

2. Usuwanie plików i katalogów

Files.delete(path)

Usuwa plik albo pusty katalog. Jeśli katalog nie jest pusty — zostanie rzucony DirectoryNotEmptyException.

Path dir = Paths.get("testDir");
try {
    Files.delete(dir);
    System.out.println("Katalog usunięto: " + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
    System.out.println("Nie można usunąć: katalog nie jest pusty!");
}

Files.deleteIfExists(path)

Działa jak delete, ale nie zgłasza błędu, gdy obiekt nie istnieje. Zwraca true, jeśli coś zostało usunięte, i false — jeśli obiektu nie było.

Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
    System.out.println("Plik usunięty.");
} else {
    System.out.println("Pliku nie znaleziono, nic nie usunięto.");
}

Jak usunąć niepusty katalog?

Nie da się ot tak usunąć niepustego folderu. Najpierw trzeba usunąć całą jego zawartość (pliki i podkatalogi), a następnie sam folder. Robi się to rekurencyjnie, np. przez 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("Katalog i cała jego zawartość zostały usunięte.");
        }
    }
}

Jeśli dopiero zaczynasz, nie przerażaj się tym kodem — później omówimy walkFileTree dokładniej.

3. Przeglądanie zawartości katalogu

Files.list(path)

Zwraca Stream<Path> — strumień ścieżek. Możesz przetwarzać zawartość folderu za pomocą Stream API. Każdy element — plik lub podkatalog (bez rekurencji!).

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()));
    }
}

Ważna uwaga: strumień trzeba koniecznie zamknąć, dlatego używamy try‑with‑resources.

Przykład: wypisywanie nazw plików i podkatalogów

Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
    stream.forEach(path -> {
        String type = Files.isDirectory(path) ? "katalog" : "plik";
        System.out.println(path.getFileName() + " — " + type);
    });
}

Uzyskanie listy plików jako kolekcji

List<Path> files = Files.list(reports2024)
    .filter(Files::isRegularFile)
    .toList();

System.out.println("Pliki w folderze:");
files.forEach(System.out::println);

Ważne: Files.list(path) zwraca tylko zawartość bieżącego katalogu (najwyższy poziom). Do rekurencyjnego przejścia użyj Files.walk(path).

4. Praktyka: mini‑menedżer plików

Narzędzie tworzy katalog mydata/logs, plik log1.txt, wypisuje zawartość folderu i następnie wszystko usuwa.

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, "Cześć, log!");

        System.out.println("Zawartość folderu " + logsDir + ":");
        try (var stream = Files.list(logsDir)) {
            stream.forEach(path -> System.out.println(" - " + path.getFileName()));
        }

        Files.deleteIfExists(logFile);
        Files.deleteIfExists(logsDir);
        System.out.println("Plik i folder zostały usunięte.");
    }
}

Komentarze do kodu:

  • Files.createDirectories gwarantuje utworzenie całego łańcucha.
  • resolve — wygodny sposób dodania do ścieżki nazwy pliku.
  • Zamykamy strumień z Files.list przez try‑with‑resources — szczególnie istotne w Windows.

5. Specyfika i niuanse

Sprawdzenie istnienia

Przed utworzeniem/usunięciem warto sprawdzić, czy ścieżka istnieje:

if (!Files.exists(path)) {
    Files.createDirectory(path);
}

Uprawnienia dostępu

Jeśli program nie ma uprawnień do tworzenia/usuwania — otrzymasz AccessDeniedException. Na przykład utworzenie folderu w katalogu głównym dysku przez zwykłego użytkownika prawie zawsze zakończy się błędem.

Pusta i niepusta direktoria

Usunąć można tylko pusty katalog (Files.delete). Do usuwania wraz z całą zawartością użyj przejścia rekurencyjnego (walkFileTree).

Wieloplatformowość

API java.nio.file poprawnie działa na wszystkich popularnych systemach operacyjnych i uwzględnia separatory ścieżek. Do budowania ścieżek używaj Paths.get i Path.resolve, a nie sklejaj łańcuchów.

Linki symboliczne

W podstawowych zadaniach nie trzeba o nich myśleć, ale jeśli spotkasz „nietypowe” wpisy, które nie są ani zwykłym plikiem, ani katalogiem — możliwe, że to symlinki. Wrócimy do nich w bardziej zaawansowanych wykładach.

6. Typowe błędy przy pracy z katalogami

Błąd nr 1: próba usunięcia niepustego katalogu prostym wywołaniem Files.delete(path). Java rzuci DirectoryNotEmptyException. Najpierw usuń zawartość, potem sam folder.

Błąd nr 2: zapomniano zamknąć strumień z Files.list(). Jeśli nie użyjesz try‑with‑resources, strumień pozostanie otwarty i w Windows może wystąpić błąd przy usuwaniu folderu.

Błąd nr 3: tworzenie katalogu bez sprawdzenia istnienia katalogu nadrzędnego. Wywołanie Files.createDirectory dla ścieżki typu parent/child, gdy parent nie istnieje, spowoduje NoSuchFileException. Użyj Files.createDirectories.

Błąd nr 4: używanie ścieżek bezwzględnych bez potrzeby. Preferuj ścieżki względne w obrębie projektu — dzięki temu kod będzie bardziej przenośny.

Błąd nr 5: brak obsługi IOException. Każda operacja na systemie plików może zakończyć się błędem. Opakuj w try-catch albo przekaż wyjątek wyżej.

Błąd nr 6: próba utworzenia/usunięcia w folderze, do którego brak uprawnień. W takim przypadku otrzymasz AccessDeniedException. Sprawdź kontekst uruchomienia i uprawnienia dostępu.

1
Ankieta/quiz
Praca z plikami, poziom 35, lekcja 4
Niedostępny
Praca z plikami
Praca z plikami
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION