JavaRush /Курсы /JAVA 25 SELF /Работа с директориями: создание, удаление, просмотр содер...

Работа с директориями: создание, удаление, просмотр содержимого

JAVA 25 SELF
35 уровень , 4 лекция
Открыта

1. Создание директорий

Директория (она же папка) — это не просто контейнер для файлов, а основа организации данных на диске. В приложениях мы постоянно создаём каталоги для входных/выходных данных, логов, временных файлов и т.д. Современный API java.nio.file делает это удобно и кроссплатформенно.

Давайте посмотрим, как создавать, удалять и просматривать содержимое папок с помощью классов Files, Path и Paths.

Files.createDirectory(path)

Создаёт одну директорию по указанному пути. Если родительская директория отсутствует — будет выброшено исключение.

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("Директория создана: " + dir.toAbsolutePath());
        } else {
            System.out.println("Директория уже существует: " + dir.toAbsolutePath());
        }
    }
}

Если вы попробуете создать директорию, которая уже есть, получите FileAlreadyExistsException.

Files.createDirectories(path)

Создаёт всю цепочку директорий. Если какой-то из промежуточных каталогов отсутствует — он будет создан автоматически. Если часть цепочки уже существует — ошибки не будет.

Path nestedDir = Paths.get("parent/child/grandchild");
Files.createDirectories(nestedDir);
System.out.println("Создана цепочка директорий: " + nestedDir.toAbsolutePath());

Это как если бы вы попросили Java построить не только дом, но и подъезд, и улицу, если их ещё не было.

Типичный пример: создаём структуру для проекта

Допустим, нужно сохранять отчёты в папку output/reports/2024. Не проверяйте каждую директорию вручную — используйте createDirectories.

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

Java сама разберётся, что уже есть, а что нужно создать.

2. Удаление файлов и директорий

Files.delete(path)

Удаляет файл или пустую директорию. Если директория не пуста — будет выброшено DirectoryNotEmptyException.

Path dir = Paths.get("testDir");
try {
    Files.delete(dir);
    System.out.println("Директория удалена: " + dir.toAbsolutePath());
} catch (DirectoryNotEmptyException e) {
    System.out.println("Невозможно удалить: директория не пуста!");
}

Files.deleteIfExists(path)

Работает как delete, но не выбрасывает ошибку, если объекта нет. Возвращает true, если что-то было удалено, и false — если объекта не было.

Path file = Paths.get("output/reports/2024/report.txt");
if (Files.deleteIfExists(file)) {
    System.out.println("Файл удалён.");
} else {
    System.out.println("Файл не найден, ничего не удалено.");
}

Как удалить непустую директорию?

Непустую папку просто так удалить нельзя. Сначала нужно удалить всё её содержимое (файлы и поддиректории), а затем саму папку. Делается это рекурсивно, например, через 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("Директория и все её содержимое удалены.");
        }
    }
}

Если вы только начинаете, не пугайтесь этого кода — позже разберём walkFileTree подробнее.

3. Просмотр содержимого директории

Files.list(path)

Возвращает Stream<Path> — поток путей. Вы можете обрабатывать содержимое папки через Stream API. Каждая запись — файл или поддиректория (без рекурсии!).

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

Важная деталь: поток обязательно нужно закрывать, поэтому используем try‑with‑resources.

Пример: выводим имена файлов и поддиректорий

Path reports2024 = Paths.get("output/reports/2024");
try (var stream = Files.list(reports2024)) {
    stream.forEach(path -> {
        String type = Files.isDirectory(path) ? "директория" : "файл";
        System.out.println(path.getFileName() + " — " + type);
    });
}

Получение списка файлов в виде коллекции

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

System.out.println("Файлы в папке:");
files.forEach(System.out::println);

Важно: Files.list(path) возвращает только содержимое текущей директории (верхний уровень). Для рекурсивного обхода используйте Files.walk(path).

4. Практика: мини‑файловый менеджер

Утилита создаёт директорию mydata/logs, файл log1.txt, выводит содержимое папки и затем всё удаляет.

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, "Привет, лог!");

        System.out.println("Содержимое папки " + logsDir + ":");
        try (var stream = Files.list(logsDir)) {
            stream.forEach(path -> System.out.println(" - " + path.getFileName()));
        }

        Files.deleteIfExists(logFile);
        Files.deleteIfExists(logsDir);
        System.out.println("Файл и папка удалены.");
    }
}

Комментарии к коду:

  • Files.createDirectories гарантирует создание всей цепочки.
  • resolve — удобный способ добавить к пути имя файла.
  • Закрываем поток от Files.list через try‑with‑resources — особенно критично в Windows.

5. Особенности и нюансы

Проверка существования

Перед созданием/удалением полезно проверить, существует ли путь:

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

Права доступа

Если у программы нет прав на создание/удаление — получите AccessDeniedException. Например, создание папки в корне диска от обычного пользователя почти всегда закончится ошибкой.

Пустая и непустая директория

Удалить можно только пустую директорию (Files.delete). Для удаления со всем содержимым используйте рекурсивный обход (walkFileTree).

Кроссплатформенность

API java.nio.file корректно работает на всех популярных ОС и учитывает разделители путей. Для построения путей используйте Paths.get и Path.resolve, а не склеивайте строки.

Символические ссылки

В базовых задачах о них можно не думать, но если встретите «необычные» записи, которые не являются ни обычным файлом, ни директорией — возможно, это симлинки. К ним вернёмся в продвинутых лекциях.

6. Типичные ошибки при работе с директориями

Ошибка №1: попытка удалить непустую директорию простым вызовом Files.delete(path). Java выбросит DirectoryNotEmptyException. Сначала удалите содержимое, затем саму папку.

Ошибка №2: забыли закрыть поток из Files.list(). Если не использовать try‑with‑resources, поток останется открытым, и на Windows возможна ошибка при удалении папки.

Ошибка №3: создание директории без проверки наличия родителя. Вызов Files.createDirectory для пути вида parent/child, когда parent не существует, приведёт к NoSuchFileException. Используйте Files.createDirectories.

Ошибка №4: использование абсолютных путей без необходимости. Предпочитайте относительные пути внутри проекта — так код будет переносимее.

Ошибка №5: не обрабатывается IOException. Любая операция с ФС может завершиться ошибкой. Оборачивайте в try-catch или пробрасывайте исключение выше.

Ошибка №6: попытка создать/удалить в папке, к которой нет прав. В этом случае получите AccessDeniedException. Проверьте контекст запуска и права доступа.

1
Задача
JAVA 25 SELF, 35 уровень, 4 лекция
Недоступна
Организуем отчёты: Годовые папки 📂
Организуем отчёты: Годовые папки 📂
1
Задача
JAVA 25 SELF, 35 уровень, 4 лекция
Недоступна
Инвентаризация в хранилище игровых ассетов 📦
Инвентаризация в хранилище игровых ассетов 📦
1
Опрос
Работа с файлами, 35 уровень, 4 лекция
Недоступен
Работа с файлами
Работа с файлами
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Shanechka Уровень 46
28 декабря 2025
Все круто, но в примерах решения периодически встречаются старые способы, а не те, что в лекции, как вариант решения последней задачки по мотивам лекции:

public class Solution {
    public static void main(String[] args) throws IOException {
        // Путь к директории "game_assets" в текущем рабочем каталоге
        Path assetsDir = Paths.get("game_assets");

        // Создаём директорию, если её ещё нет
        Files.createDirectories(assetsDir);

        // Пути к файлам-заглушкам внутри директории
        Path characterModel = assetsDir.resolve("character_model.obj");
        Path environmentTexture = assetsDir.resolve("environment_texture.png");

        // Создаём пустые файлы, если они ещё не существуют
        if (Files.notExists(characterModel)) {
            Files.createFile(characterModel);
        }
        if (Files.notExists(environmentTexture)) {
            Files.createFile(environmentTexture);
        }

        try (var stream = Files.list(assetsDir)) {
            stream.forEach(path -> System.out.println(path.getFileName()));
        }
    }
}