1. Чтение базовых атрибутов: BasicFileAttributes
Когда мы говорим о файле или папке, мы имеем в виду не только его имя или размер. У каждого файла есть «паспорт» — набор атрибутов, который содержит:
- Время создания
- Время последнего изменения
- Время последнего доступа
- Размер
- Права доступа (кто может читать, писать, выполнять)
- Информация о владельце (на Unix)
- Признаки «скрытый», «только для чтения» и др.
В Java для работы с этими атрибутами есть удобный и мощный API в пакете java.nio.file.attribute. Не нужно писать платформозависимый код: всё необходимое есть в стандартной библиотеке.
Для начала — импортируем нужные классы:
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
Как получить базовые атрибуты файла?
Используем метод Files.readAttributes:
Path path = Paths.get("example.txt");
try {
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("Создан: " + attrs.creationTime());
System.out.println("Изменён: " + attrs.lastModifiedTime());
System.out.println("Последний доступ: " + attrs.lastAccessTime());
System.out.println("Размер: " + attrs.size());
System.out.println("Это директория? " + attrs.isDirectory());
System.out.println("Это файл? " + attrs.isRegularFile());
System.out.println("Это символическая ссылка? " + attrs.isSymbolicLink());
} catch (IOException e) {
System.out.println("Ошибка при чтении атрибутов: " + e.getMessage());
}
Представьте, что вы инспектор и пришли проверить квартиру. Вы не только смотрите, есть ли дверь (файл существует), но и спрашиваете у жильцов: «Когда построили дом? Когда последний раз делали ремонт? Кто хозяин?».
Кратко о свойствах BasicFileAttributes
| Свойство | Что возвращает? |
|---|---|
|
Дата и время создания файла/папки |
|
Дата и время последнего изменения |
|
Дата и время последнего доступа |
|
Размер файла (в байтах) |
|
Это директория? |
|
Это обычный файл? |
|
Это символическая ссылка? |
2. Расширенные атрибуты: POSIX и DOS
POSIX-атрибуты (Linux, macOS и другие Unix-подобные ОС)
Если вы работаете на Unix-системе, можно получить расширенную информацию: права доступа, владелец, группа.
try {
PosixFileAttributes posixAttrs = Files.readAttributes(path, PosixFileAttributes.class);
System.out.println("Владелец: " + posixAttrs.owner().getName());
System.out.println("Группа: " + posixAttrs.group().getName());
System.out.println("Права доступа: " + PosixFilePermissions.toString(posixAttrs.permissions()));
} catch (UnsupportedOperationException e) {
System.out.println("POSIX-атрибуты не поддерживаются на этой ОС.");
} catch (IOException e) {
System.out.println("Ошибка при чтении POSIX-атрибутов: " + e.getMessage());
}
Примечание: На Windows этот код выбросит UnsupportedOperationException — это нормально.
DOS-атрибуты (Windows)
На Windows можно работать с признаками «только для чтения», «скрытый», «архивный», «системный»:
try {
DosFileAttributes dosAttrs = Files.readAttributes(path, DosFileAttributes.class);
System.out.println("Скрытый: " + dosAttrs.isHidden());
System.out.println("Только для чтения: " + dosAttrs.isReadOnly());
System.out.println("Системный: " + dosAttrs.isSystem());
System.out.println("Архивный: " + dosAttrs.isArchive());
} catch (UnsupportedOperationException e) {
System.out.println("DOS-атрибуты не поддерживаются на этой ОС.");
} catch (IOException e) {
System.out.println("Ошибка при чтении DOS-атрибутов: " + e.getMessage());
}
3. Изменение атрибутов файлов
Читать чужие паспорта — это одно, а вот менять дату рождения или фамилию — другое дело! В Java мы можем менять атрибуты файлов (разумеется, с нужными правами).
Изменение времени последней модификации
import java.nio.file.attribute.FileTime;
Path file = Paths.get("example.txt");
try {
FileTime newTime = FileTime.fromMillis(System.currentTimeMillis() - 24 * 60 * 60 * 1000); // минус 1 день
Files.setLastModifiedTime(file, newTime);
System.out.println("Время последней модификации изменено!");
} catch (IOException e) {
System.out.println("Ошибка при изменении времени: " + e.getMessage());
}
Изменение прав доступа (POSIX)
Только для Unix-систем! Например, сделать файл исполняемым для всех:
try {
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-xr-x");
Files.setPosixFilePermissions(file, perms);
System.out.println("Права доступа изменены!");
} catch (UnsupportedOperationException e) {
System.out.println("POSIX-права не поддерживаются на этой ОС.");
} catch (IOException e) {
System.out.println("Ошибка при изменении прав: " + e.getMessage());
}
Пояснение к строке "rwxr-xr-x":
- r — read (чтение)
- w — write (запись)
- x — execute (исполнение)
- Первый блок из 3 символов — владелец, второй — группа, третий — остальные.
Изменение скрытого/только для чтения статуса (DOS-атрибуты, Windows)
Сделать файл скрытым:
try {
Files.setAttribute(file, "dos:hidden", true);
System.out.println("Файл стал скрытым (Windows)!");
} catch (UnsupportedOperationException e) {
System.out.println("DOS-атрибуты не поддерживаются на этой ОС.");
} catch (IOException e) {
System.out.println("Ошибка при изменении атрибута: " + e.getMessage());
}
Сделать файл «только для чтения»:
try {
Files.setAttribute(file, "dos:readonly", true);
System.out.println("Файл теперь только для чтения (Windows)!");
} catch (UnsupportedOperationException e) {
System.out.println("DOS-атрибуты не поддерживаются на этой ОС.");
} catch (IOException e) {
System.out.println("Ошибка при изменении атрибута: " + e.getMessage());
}
4. Проверка прав доступа
Иногда важно быстро проверить, можно ли открыть файл для чтения, записи или исполнения:
Path file = Paths.get("example.txt");
System.out.println("Чтение разрешено: " + Files.isReadable(file));
System.out.println("Запись разрешена: " + Files.isWritable(file));
System.out.println("Исполнение разрешено: " + Files.isExecutable(file));
Это работает одинаково на всех платформах, хотя реальное поведение зависит от ОС и настроек безопасности.
5. Практика: вывод подробной информации о файле
Напишем мини-программу, которая по пути к файлу покажет максимум информации и попробует изменить некоторые атрибуты.
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.Set;
import java.io.IOException;
public class FileAttributesDemo {
public static void main(String[] args) throws IOException {
Path path = Paths.get("example.txt");
if (!Files.exists(path)) {
System.out.println("Файл не найден!");
return;
}
// Базовые атрибуты
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println("Имя: " + path.getFileName());
System.out.println("Путь: " + path.toAbsolutePath());
System.out.println("Размер: " + attrs.size() + " байт");
System.out.println("Создан: " + attrs.creationTime());
System.out.println("Изменён: " + attrs.lastModifiedTime());
System.out.println("Последний доступ: " + attrs.lastAccessTime());
System.out.println("Это директория? " + attrs.isDirectory());
System.out.println("Это файл? " + attrs.isRegularFile());
// Проверка прав доступа
System.out.println("Чтение разрешено: " + Files.isReadable(path));
System.out.println("Запись разрешена: " + Files.isWritable(path));
System.out.println("Исполнение разрешено: " + Files.isExecutable(path));
// Попробуем изменить время модификации
FileTime now = FileTime.fromMillis(System.currentTimeMillis());
Files.setLastModifiedTime(path, now);
System.out.println("Время последней модификации обновлено!");
// Попробуем сделать файл скрытым (если поддерживается)
try {
Files.setAttribute(path, "dos:hidden", true);
System.out.println("Файл стал скрытым (если поддерживается ОС).");
} catch (UnsupportedOperationException e) {
System.out.println("Скрытые файлы не поддерживаются на этой ОС.");
}
// Попробуем вывести POSIX-права (если поддерживается)
try {
PosixFileAttributes posixAttrs = Files.readAttributes(path, PosixFileAttributes.class);
System.out.println("Владелец: " + posixAttrs.owner().getName());
System.out.println("Права доступа: " + PosixFilePermissions.toString(posixAttrs.permissions()));
} catch (UnsupportedOperationException e) {
System.out.println("POSIX-атрибуты не поддерживаются на этой ОС.");
}
}
}
6. Полезные нюансы
Кроссплатформенные различия и советы
- Не все атрибуты доступны на всех ОС! На Windows нет POSIX-прав, а на Linux нет DOS-атрибутов.
- Всегда используйте try-catch! Методы могут выбрасывать UnsupportedOperationException или IOException.
- Права доступа — это не всегда только «rwx»! На Windows модель прав другая, «только для чтения» может задаваться политикой безопасности ОС.
- Скрытые файлы — понятие относительное. На Unix файл скрыт, если имя начинается с точки (.hidden), на Windows — если установлен атрибут dos:hidden.
Таблица: какие атрибуты где доступны
| Атрибут | Windows (dos:*) | Linux/macOS (posix:*) |
|---|---|---|
| Время создания | + | + |
| Время последнего изменения | + | + |
| Время последнего доступа | + | + |
| Скрытый файл | + | Только имя с точкой |
| Только для чтения | + | + |
| Права доступа (rwx) | - | + |
| Владелец, группа | - | + |
| Архивный, системный | + | - |
7. Типичные ошибки при работе с атрибутами файлов
Ошибка №1: Попытка прочитать или изменить POSIX-атрибуты на Windows. На Windows вы получите UnsupportedOperationException. Всегда обрабатывайте это исключение, если пишете кроссплатформенный код.
Ошибка №2: Изменение времени модификации файла, который открыт другим процессом. В некоторых системах файл может быть заблокирован, и операция завершится с ошибкой.
Ошибка №3: Ожидание, что операция «скрыть файл» сработает одинаково на всех ОС. На Unix скрыт файл, начинающийся с точки (.gitignore), а на Windows — если выставлен атрибут dos:hidden. Не путайте эти подходы.
Ошибка №4: Пренебрежение проверкой существования файла перед операцией. Если файла нет, получите NoSuchFileException при попытке получить атрибуты или изменить их.
Ошибка №5: Отсутствие проверки прав доступа. Если у пользователя нет прав на изменение атрибутов, операция завершится с ошибкой. Перед изменениями проверяйте Files.isWritable(path).
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ