1. Повторення: File vs Path vs Files
Старий добрий File
Так… У Java‑проєктах legacy‑коду вистачає. Тож згадаймо ще раз про ветерана Java, клас File. Він з’явився у мові ще в першій версії й дозволяє працювати з файлами й теками: дізнаватися, чи існує файл, його ім’я, розмір, дату зміни, створювати й видаляти файли та теки. Як ми з вами вже знаємо, він сповнений недоліків: частина методів працює неінтуїтивно, не всі операції підтримуються кросплатформно, а деякі методи повертають не винятки, а просто false (що не завжди зручно для налагодження).
import java.io.File;
File file = new File("example.txt");
System.out.println("Чи існує файл? " + file.exists());
System.out.println("Це файл? " + file.isFile());
System.out.println("Це тека? " + file.isDirectory());
Path і Files: сучасний погляд (Java 7+)
З виходом Java 7 з’явився пакет java.nio.file, який пропонує потужніші й гнучкіші інструменти. Два ключові інструменти:
- Path — інтерфейс, що описує шлях до файлу або теки. Можна сказати, що це «рядок із інтелектом»: уміє розбирати, з’єднувати, аналізувати, порівнювати шляхи.
- Files — утилітарний клас із великою кількістю статичних методів для роботи з файлами й директоріями: створення, видалення, копіювання, читання, запис, отримання інформації.
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("example.txt");
System.out.println("Шлях: " + path);
Цікавий факт: клас Path — не просто рядок! Він знає про роздільники директорій, уміє розбирати відносні та абсолютні шляхи й однаково добре працює на Windows і Linux.
Таблиця порівняння File і Path/Files
| Критерій | File (старий API) | Path + Files (сучасний API) |
|---|---|---|
| Синтаксис | ООП-стиль | Комбінація Path + статичні методи Files |
| Кросплатформність | Часткова | Відмінна; враховує ОС |
| Винятки | Не завжди | Майже завжди |
| Нові можливості | Ні | Так (атрибути, права, посилання тощо) |
| Рекомендується | Швидше ні | Так |
2. Отримання інформації про файл/директорію
Розберемося, як дізнатися все найважливіше про файл або теку: чи існує об’єкт, тип (файл чи директорія), розмір, ім’я, шлях і батьківська директорія.
Перевірка існування
Через File
File file = new File("example.txt");
if (file.exists()) {
System.out.println("Файл існує!");
} else {
System.out.println("Файл не знайдено.");
}
Через Path і Files
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Path path = Paths.get("example.txt");
if (Files.exists(path)) {
System.out.println("Файл існує!");
} else {
System.out.println("Файл не знайдено.");
}
Порада: Для нових проєктів завжди використовуйте Path і Files. Це безпечніше, зручніше й кросплатформно.
Перевірка типу: файл чи директорія
File
if (file.isFile()) {
System.out.println("Це файл.");
} else if (file.isDirectory()) {
System.out.println("Це тека.");
}
Path + Files
if (Files.isRegularFile(path)) {
System.out.println("Це файл.");
} else if (Files.isDirectory(path)) {
System.out.println("Це тека.");
}
Отримання розміру файлу
File
long size = file.length();
System.out.println("Розмір файлу: " + size + " байт");
Path + Files
try {
long size = Files.size(path);
System.out.println("Розмір файлу: " + size + " байт");
} catch (IOException e) {
System.out.println("Помилка під час отримання розміру файлу: " + e.getMessage());
}
Увага: Для теки метод length() завжди поверне 0, а Files.size(path) викине IOException. Розмір теки — це сума розмірів усіх файлів усередині (детальніше — у наступних лекціях).
Отримання абсолютного й відносного шляху
File
System.out.println("Відносний шлях: " + file.getPath());
System.out.println("Абсолютний шлях: " + file.getAbsolutePath());
Path
System.out.println("Відносний шлях: " + path);
System.out.println("Абсолютний шлях: " + path.toAbsolutePath());
Отримання імені файлу та батьківської директорії
File
System.out.println("Ім’я файлу: " + file.getName());
System.out.println("Батьківська тека: " + file.getParent());
Path
System.out.println("Ім’я файлу: " + path.getFileName());
System.out.println("Батьківська тека: " + path.getParent());
Порада: Path уміє працювати не лише з файлами, а й із теками, відносними й абсолютними шляхами, а також легко розбирає шлях на частини.
3. Отримання атрибутів файлу
Іноді потрібно дізнатися не лише розмір і ім’я файлу, а й щось цікавіше: дату створення, дату останньої зміни, права доступу.
Дата створення та останньої зміни
File (обмежено)
long lastModified = file.lastModified();
System.out.println("Дата останньої зміни: " + new java.util.Date(lastModified));
Недолік: Дізнатися дату створення файлу через File неможливо!
Path + Files
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
try {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
FileTime creationTime = attrs.creationTime();
FileTime lastModifiedTime = attrs.lastModifiedTime();
System.out.println("Дата створення: " + creationTime);
System.out.println("Дата останньої зміни: " + lastModifiedTime);
} catch (IOException e) {
System.out.println("Помилка під час отримання атрибутів: " + e.getMessage());
}
Перевірка прав доступу
File
System.out.println("Можна читати? " + file.canRead());
System.out.println("Можна записувати? " + file.canWrite());
System.out.println("Можна виконувати? " + file.canExecute());
Path + Files
System.out.println("Можна читати? " + Files.isReadable(path));
System.out.println("Можна записувати? " + Files.isWritable(path));
System.out.println("Можна виконувати? " + Files.isExecutable(path));
Цікавий факт: у Windows права доступу обмежені, а в Unix-системах можна отримати й змінити значно більше прав (наприклад, через POSIX-атрибути).
4. Типові помилки під час отримання інформації про файли
Помилка № 1: Використання File, коли потрібен Path.
Багато новачків продовжують використовувати File, бо так простіше або «бо так всюди в інтернеті». Але за допомогою Path і Files можна робити те саме, проте надійніше й сучасніше.
Помилка № 2: Перевірка типу об’єкта лише через File.
Якщо ви використовуєте лише file.isFile() і file.isDirectory(), то можете проґавити «особливі» файли (символьні посилання, пристрої). У сучасному API є Files.isRegularFile(path), Files.isDirectory(path) та інші перевірки.
Помилка № 3: Ігнорування винятків.
Методи Files.size(path) і Files.readAttributes(...) викидають IOException. Якщо не обробляти винятки, програма впаде за першої ж помилки доступу або якщо файл зникне під час роботи.
Помилка № 4: Очікування, що розмір теки можна дізнатися напряму.
Метод Files.size(path) для теки спричинить виняток. Щоб дізнатися розмір теки, потрібно рекурсивно підсумувати розміри всіх файлів усередині.
Помилка № 5: Недостатня перевірка прав доступу.
Навіть якщо файл існує, у вас може не бути прав на його читання чи запис. Завжди перевіряйте права перед операціями: Files.isReadable(path), Files.isWritable(path), Files.isExecutable(path).
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ