Работа с файловой системой в Java: на практике
В современной разработке на Java работа с файловой системой — одна из фундаментальных задач. Будь то сохранение конфигураций, обработка логов или загрузка пользовательских данных, умение грамотно взаимодействовать с файлами и директориями необходимо каждому разработчику. В этой статье мы разберём практические аспекты работы с файловой системой в Java, используя как классический подход (класс File), так и современный API NIO.2 (Path, Files).
Материал ориентирован на практиков: вы получите готовые примеры кода, которые можно сразу использовать в своих проектах. Рассмотрим создание, чтение, запись, копирование и удаление файлов, а также работу с директориями.
Классический подход: класс File
До появления Java 7 основным инструментом для работы с файловой системой был класс java.io.File. Несмотря на то, что он считается устаревшим, его всё ещё можно встретить в легаси-проектах. Рассмотрим основные операции.
Создание файла:
import java.io.File;
import java.io.IOException;
public class FileExample {
public static void main(String[] args) {
File file = new File("example.txt");
try {
if (file.createNewFile()) {
System.out.println("Файл создан: " + file.getName());
} else {
System.out.println("Файл уже существует.");
}
} catch (IOException e) {
System.out.println("Ошибка при создании файла: " + e.getMessage());
}
}
}
Проверка существования и свойств файла:
File file = new File("example.txt");
if (file.exists()) {
System.out.println("Файл существует");
System.out.println("Абсолютный путь: " + file.getAbsolutePath());
System.out.println("Размер: " + file.length() + " байт");
System.out.println("Читаемый: " + file.canRead());
System.out.println("Записываемый: " + file.canWrite());
}
exists()— проверяет, существует ли файл или директория.isFile()— является ли объект файлом.isDirectory()— является ли объект директорией.length()— возвращает размер файла в байтах.delete()— удаляет файл или пустую директорию.
Недостаток класса File — отсутствие поддержки символических ссылок, метаданных и ограниченная работа с исключениями. Для новых проектов рекомендуется использовать NIO.2.
Современный подход: NIO.2 (Path и Files)
Начиная с Java 7, в состав JDK вошёл пакет java.nio.file, предоставляющий более гибкий и производительный API. Основные классы: Path (представляет путь к файлу или директории) и Files (содержит статические методы для операций).
Создание файла с помощью Files:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
public class NioExample {
public static void main(String[] args) {
Path path = Paths.get("nio_example.txt");
try {
Files.createFile(path);
System.out.println("Файл создан: " + path.toAbsolutePath());
} catch (IOException e) {
System.out.println("Ошибка: " + e.getMessage());
}
}
}
Создание директорий:
Path dirPath = Paths.get("myDir/subDir");
try {
Files.createDirectories(dirPath); // создаёт все недостающие родительские директории
System.out.println("Директория создана: " + dirPath);
} catch (IOException e) {
e.printStackTrace();
}
Чтение и запись файлов:
Самый простой способ прочитать все строки файла:
Path filePath = Paths.get("data.txt");
try {
List<String> lines = Files.readAllLines(filePath);
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
Запись в файл:
List<String> content = Arrays.asList("Строка 1", "Строка 2", "Строка 3");
Path outputPath = Paths.get("output.txt");
try {
Files.write(outputPath, content);
System.out.println("Данные записаны в файл.");
} catch (IOException e) {
e.printStackTrace();
}
Files.readAllLines()— читает все строки в список.Files.write()— записывает коллекцию строк в файл (перезаписывает).Files.readAllBytes()— читает все байты (для бинарных файлов).Files.write()с параметромStandardOpenOption.APPEND— добавляет данные в конец файла.
Копирование, перемещение и удаление файлов
NIO.2 предоставляет удобные методы для этих операций с возможностью указания опций.
Копирование файла:
Path source = Paths.get("source.txt");
Path target = Paths.get("backup/source_copy.txt");
try {
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Файл скопирован.");
} catch (IOException e) {
e.printStackTrace();
}
Перемещение (переименование):
Path source = Paths.get("old_name.txt");
Path target = Paths.get("new_name.txt");
try {
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
System.out.println("Файл перемещён/переименован.");
} catch (IOException e) {
e.printStackTrace();
}
Удаление файла или директории:
Path fileToDelete = Paths.get("temp.txt");
try {
Files.delete(fileToDelete);
System.out.println("Файл удалён.");
} catch (IOException e) {
e.printStackTrace();
}
// Безопасное удаление (не выбрасывает исключение, если файла нет)
boolean deleted = Files.deleteIfExists(fileToDelete);
System.out.println("Удалён: " + deleted);
Важно: Files.delete() удаляет только пустые директории. Для рекурсивного удаления нужно обходить дерево вручную или использовать сторонние библиотеки.
Обход файловой системы и работа с фильтрами
Часто требуется найти все файлы определённого типа в директории. NIO.2 предлагает удобный метод Files.walk() для рекурсивного об