Gymterview
middle

Как работать с файлами и каталогами через Files API?

Класс java.nio.file.Files предоставляет исчерпывающий набор статических методов для работы с файлами и каталогами, покрывающий все основные сценарии: чтение, запись, копирование, удаление, создание каталогов, обход дерева и проверку атрибутов.

Чтение и запись файлов

Примеры чтения и записи
Path path = Path.of("example.txt");

// Запись строки в файл (Java 11+)
Files.writeString(path, "Привет, мир!\nВторая строка.", StandardCharsets.UTF_8);

// Запись списка строк
Files.write(path, List.of("строка 1", "строка 2"), StandardCharsets.UTF_8);

// Дозапись в файл
Files.writeString(path, "\nДополнение",
    StandardCharsets.UTF_8, StandardOpenOption.APPEND);

// Чтение всего содержимого (Java 11+)
String content = Files.readString(path, StandardCharsets.UTF_8);

// Чтение построчно в список
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);

// Ленивое чтение через Stream (для больших файлов)
try (Stream<String> stream = Files.lines(path)) {
    stream.filter(l -> l.contains("ERROR")).forEach(System.out::println);
}

Копирование, перемещение и удаление

Примеры операций с файлами
Path source = Path.of("source.txt");
Path target = Path.of("backup/source_copy.txt");

// Копирование с заменой существующего
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

// Копирование из InputStream в файл
try (InputStream is = new URL("https://example.com/file.txt").openStream()) {
    Files.copy(is, target, StandardCopyOption.REPLACE_EXISTING);
}

// Атомарное перемещение
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);

// Удаление
Files.delete(path);              // бросает NoSuchFileException
Files.deleteIfExists(path);      // возвращает false

Создание каталогов и временных файлов

Пример
Files.createDirectory(Path.of("new_dir"));          // один каталог
Files.createDirectories(Path.of("a/b/c/d"));        // вложенные (mkdir -p)
Path tempFile = Files.createTempFile("prefix_", ".tmp");
Path tempDir = Files.createTempDirectory("my_temp_");

Обход дерева каталогов

Примеры обхода
// Files.list — только первый уровень
try (Stream<Path> stream = Files.list(Path.of("src"))) {
    stream.filter(Files::isRegularFile).forEach(System.out::println);
}

// Files.walk — рекурсивный обход
try (Stream<Path> stream = Files.walk(Path.of("/project/src"))) {
    List<Path> javaFiles = stream
        .filter(Files::isRegularFile)
        .filter(p -> p.toString().endsWith(".java"))
        .collect(Collectors.toList());
}

// Files.walkFileTree — продвинутый обход (например, рекурсивное удаление)
Files.walkFileTree(Path.of("dir_to_delete"), new SimpleFileVisitor<>() {
    @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;
    }
});

Проверка свойств файлов

Пример
boolean exists = Files.exists(path);
boolean isFile = Files.isRegularFile(path);
boolean isDir = Files.isDirectory(path);
boolean isLink = Files.isSymbolicLink(path);
long size = Files.size(path);
String mimeType = Files.probeContentType(path); // "text/plain"

Важное

  • Все методы Files, возвращающие Stream (list(), walk(), find(), lines()), требуют try-with-resources.
  • Files.createDirectories() не бросает исключение, если каталог уже существует.
  • DirectoryStream — это Iterable, а не Stream из Java 8.
  • Для рекурсивного удаления каталога необходим обход через walkFileTreeFiles.delete() не удаляет непустой каталог.

На собеседовании: продемонстрируйте знание основных операций: чтение/запись, обход дерева, копирование/перемещение. Упомяните обязательность try-with-resources для Stream-методов и невозможность удалить непустой каталог одним вызовом.