Gymterview
middle

Что такое NIO.2 и чем он отличается от java.io.File?

NIO.2 (пакет java.nio.file) — это API для работы с файловой системой, появившееся в Java 7 как замена устаревшему классу java.io.File. Центральные элементы — интерфейс Path и утилитный класс Files.

Path vs File

Path — это интерфейс, представляющий путь в файловой системе. Объекты Path являются неизменяемыми (immutable), что обеспечивает потокобезопасность и предсказуемость.

Пример
// Старый подход — java.io.File
File file = new File("/home/user/data.txt");

// Новый подход — java.nio.file.Path
Path path = Path.of("/home/user/data.txt");            // Java 11+
Path path2 = Paths.get("/home/user/data.txt");          // Java 7+
Path path3 = Path.of("/home", "user", "data.txt");      // составной путь

Основные отличия

Характеристика java.io.File java.nio.file.Path + Files
Тип Класс Path — интерфейс
Иммутабельность Нет Да
Обработка ошибок Возвращает false/null Бросает информативные исключения (NoSuchFileException, AccessDeniedException)
Символьные ссылки Ограниченная поддержка Полная поддержка
Метаданные файлов Ограниченный набор Полный набор атрибутов через Files.readAttributes()
Обход дерева Ручная рекурсия Files.walk(), Files.walkFileTree()
Stream API Нет Files.lines(), Files.list(), Files.walk()

Класс Files

Files предоставляет статические методы для всех операций с файлами и каталогами.

Примеры работы с Files
// Чтение и запись (Java 11+)
String content = Files.readString(Path.of("file.txt"));
Files.writeString(Path.of("output.txt"), "Содержимое", StandardCharsets.UTF_8);

// Чтение и запись (Java 7+)
byte[] bytes = Files.readAllBytes(Path.of("file.txt"));
List<String> lines = Files.readAllLines(Path.of("file.txt"), StandardCharsets.UTF_8);

// Ленивое чтение строк (возвращает Stream)
try (Stream<String> stream = Files.lines(Path.of("large_file.txt"))) {
    stream.filter(line -> line.contains("ERROR"))
          .forEach(System.out::println);
}

// Обход дерева каталогов
try (Stream<Path> paths = Files.walk(Path.of("/home/user"))) {
    paths.filter(Files::isRegularFile)
         .filter(p -> p.toString().endsWith(".java"))
         .forEach(System.out::println);
}

// Копирование, перемещение, удаление
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE);
Files.deleteIfExists(path);

Преобразование между File и Path

Пример
File file = new File("data.txt");
Path path = file.toPath();         // File -> Path

Path path2 = Path.of("data.txt");
File file2 = path2.toFile();       // Path -> File

Частые ошибки

  • Забывают закрывать Stream от Files.lines() и Files.walk() — утечка файловых дескрипторов.
  • Используют Files.readAllLines() для огромных файлов — весь файл загружается в память.
  • Не указывают StandardCopyOption.REPLACE_EXISTING при копировании.
  • Путают Files.delete() (бросает исключение) и Files.deleteIfExists() (возвращает boolean).

На собеседовании: назовите ключевые преимущества NIO.2: иммутабельный Path, информативные исключения, полная поддержка символьных ссылок, интеграция со Stream API. Использование java.io.File в новом коде считается устаревшей практикой.