NIO: Files и Path
NIO (New I/O, Java 7+) — современный способ работать с файловой системой. Старый java.io.File неудобен: нет нормальной обработки ошибок, нет поддержки символических ссылок. java.nio.file.Path и java.nio.file.Files — современная замена, которую сейчас используют в реальных проектах.
Path — путь к файлу или директории:
Path file = Path.of("src/main/resources/config.yml"); // относительный
Path abs = Path.of("/home/user/data", "file.txt"); // абсолютный
file.getFileName() // config.yml
file.getParent() // src/main/resources
file.toAbsolutePath() // /home/user/project/src/...
Files — утилитный класс для всех операций:
// Читать весь файл сразу
String content = Files.readString(Path.of("note.txt"), StandardCharsets.UTF_8);
List<String> lines = Files.readAllLines(Path.of("log.txt"), StandardCharsets.UTF_8);
// Записать
Files.writeString(Path.of("out.txt"), "Hello!", StandardCharsets.UTF_8);
Files.write(Path.of("data.bin"), bytes);
// Копировать, переместить, удалить
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
Files.move(source, target);
Files.delete(path); // бросит если не существует
Files.deleteIfExists(path);
// Проверки
Files.exists(path)
Files.isDirectory(path)
Files.size(path) // в байтах
// Создать директории
Files.createDirectories(Path.of("a/b/c")); // создаёт все уровни
Копнуть глубже
Обход дерева файлов. Files.walk() возвращает Stream<Path> — всё дерево файлов как стрим, можно применять фильтры:
// Найти все .java файлы в проекте
try (Stream<Path> paths = Files.walk(Path.of("src"))) {
List<Path> javaFiles = paths
.filter(p -> p.toString().endsWith(".java"))
.toList();
}
Files.list(dir) — только прямые потомки директории (не рекурсивно).
Files.find(start, depth, predicate) — рекурсивно с предикатом и ограничением глубины.
WatchService — отслеживать изменения файловой системы (hot reload конфигурации, мониторинг папки):
WatchService watcher = FileSystems.getDefault().newWatchService();
Path dir = Path.of("config");
dir.register(watcher, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
WatchKey key = watcher.take(); // блокирует до события
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println("Изменён: " + event.context());
}
Каналы (Channels) и буферы — низкоуровневое NIO. FileChannel + ByteBuffer позволяют делать memory-mapped files (файл отображается в память), zero-copy передачу (transferTo), и работать с файлом напрямую, минуя Java heap. Используется в высокопроизводительных системах (Kafka внутри активно использует FileChannel.transferTo).
• как обойти дерево файлов через Files.walk и Stream (если дошёл до 2-го слоя).