«1. Обзор

В этой статье мы собираемся изучить одну из расширенных функций API-интерфейсов файловой системы Java 7 NIO.2, а именно API-интерфейсы файловых атрибутов.

Ранее мы рассмотрели API-интерфейсы File и Path, если вы хотите сначала углубиться в эти основополагающие элементы.

Все файлы, необходимые для работы с файловой системой, собраны в пакете java.nio.file:

import java.nio.file.*;

2. Основные атрибуты файлов

Давайте начнем с общего представления основных общих атрибутов. для всех файловых систем, предоставляемых BasicFileAttributeView, в котором хранятся все обязательные и необязательные видимые атрибуты файла.

Мы можем изучить основные атрибуты домашнего местоположения пользователя на текущем компьютере, создав путь к HOME и получив представление его основных атрибутов:

String HOME = System.getProperty("user.home");
Path home = Paths.get(HOME);
BasicFileAttributeView basicView = 
  Files.getFileAttributeView(home, BasicFileAttributeView.class);

После вышеуказанного шага мы теперь можем прочитать все атрибуты. пути, указанного в одной массовой операции:

BasicFileAttributes basicAttribs = basicView.readAttributes();

Теперь мы можем исследовать различные общие атрибуты, которые мы можем использовать в наших приложениях, особенно в условных операторах.

Мы можем запросить размер файла из его контейнера основных атрибутов:

@Test
public void givenPath_whenGetsFileSize_thenCorrect() {
    long size = basicAttribs.size();
    assertTrue(size > 0);
}

Мы также можем проверить, является ли это каталогом:

@Test
public void givenPath_whenChecksIfDirectory_thenCorrect() {
    boolean isDir = basicAttribs.isDirectory();
    assertTrue(isDir);
}

Или обычным файлом:

@Test
public void givenPath_whenChecksIfFile_thenCorrect() {
    boolean isFile = basicAttribs.isRegularFile();
    assertFalse(isFile);
}

С Java NIO.2 мы теперь можем иметь дело с символическими ссылками или программными ссылками в файловой системе. Это файлы или каталоги, которые мы обычно называем ярлыками.

Чтобы проверить, является ли файл символической ссылкой:

@Test
public void givenPath_whenChecksIfSymLink_thenCorrect() {
    boolean isSymLink = basicAttribs.isSymbolicLink();
    assertFalse(isSymLink);
}

В редких случаях мы можем вызвать isOther API, чтобы проверить, не принадлежит ли файл ни к одной из распространенных категорий обычных файлов, каталогов или символических ссылок:

@Test
public void givenPath_whenChecksIfOther_thenCorrect() {
    boolean isOther = basicAttribs.isOther();
    assertFalse(isOther);
}

Чтобы получить время создания файла:

FileTime created = basicAttribs.creationTime();

Чтобы получить время последнего изменения:

FileTime modified = basicAttribs.lastModifiedTime();

И чтобы получить время последнего доступа:

FileTime accessed = basicAttribs.lastAccessTime();

Все приведенные выше примеры возвращают объект FileTime. Это более удобная абстракция, чем простая отметка времени.

Например, мы можем легко сравнить время двух файлов, чтобы узнать, какое событие произошло раньше или позже другого:

@Test
public void givenFileTimes_whenComparesThem_ThenCorrect() {
    FileTime created = basicAttribs.creationTime();
    FileTime modified = basicAttribs.lastModifiedTime();
    FileTime accessed = basicAttribs.lastAccessTime();

    assertTrue(0 >= created.compareTo(accessed));
    assertTrue(0 <= modified.compareTo(created));
    assertTrue(0 == created.compareTo(created));
}

API compareTo работает так же, как и для других сопоставимых файлов в Java. Он возвращает отрицательное значение, если объект, для которого он вызывается, меньше аргумента; в нашем случае время создания определенно предшествует времени доступа, как в первом утверждении.

Во втором утверждении мы получаем положительное целое значение, потому что модификация может быть сделана только после события создания. И, наконец, он возвращает 0, когда сравниваемые моменты времени равны.

Когда у нас есть объект FileTime, мы можем преобразовать его в большинство других единиц измерения в зависимости от наших потребностей; дни, часы, минуты, секунды, миллисекунды и так далее. Мы делаем это, вызывая соответствующий API:

accessed.to(TimeUnit.SECONDS);
accessed.to(TimeUnit.HOURS);
accessed.toMillis();

Мы также можем напечатать удобочитаемую форму времени файла, вызвав его API toString:

accessed.toString();

Что напечатает что-то полезное в формате времени ISO: ~ ~~

2016-11-24T07:52:53.376Z

Мы также можем изменить атрибуты времени в представлении, вызвав его setTimes(modified, accessed, created) API. Мы передаем новые объекты FileTime, которые мы хотим изменить, или null, где мы не хотим изменяться.

Чтобы изменить время последнего доступа на одну минуту вперед, мы должны выполнить следующие шаги:

FileTime newAccessTime = FileTime.fromMillis(
  basicAttribs.lastAccessTime().toMillis() + 60000);
basicView.setTimes(null, newAccessTime , null);

Это изменение сохранится в реальном файле, как видно из любого другого приложения, работающего на машине и использующего файловую систему. .

3. Атрибуты файлового пространства

Когда вы открываете мой компьютер в Windows, Linux или Mac, вы обычно можете увидеть графический анализ информации о пространстве на ваших накопителях.

Java NIO.2 делает такую ​​высокоуровневую функциональность очень простой. Он взаимодействует с базовой файловой системой для получения этой информации, в то время как нам нужно вызывать только простые API.

Мы можем использовать класс FileStore для проверки накопителей и получения важной информации, такой как их размер, сколько места используется и сколько еще не используется.

Чтобы получить экземпляр FileStore для расположения произвольного файла в файловой системе, мы используем API класса Files getFileStore:

Path file = Paths.get("file");
FileStore store = Files.getFileStore(file);

«

long total = store.getTotalSpace();

«Этот экземпляр FileStore конкретно представляет хранилище файлов, в котором находится указанный файл, а не сам файл. Чтобы получить общее пространство:

long used = store.getTotalSpace() - store.getUnallocatedSpace();

Чтобы получить используемое пространство:

Мы с меньшей вероятностью будем следовать этому подходу, чем следующему.

Iterable<FileStore> fileStores = FileSystems.getDefault().getFileStores();

Чаще всего мы получаем информацию о хранении информации обо всех хранилищах файлов. Чтобы эмулировать информацию о пространстве на графическом диске моего компьютера в программе, мы можем использовать класс FileSystem для перечисления хранилищ файлов: графический пользовательский интерфейс:

for (FileStore fileStore : fileStores) {
    long totalSpace = fileStore.getTotalSpace();
    long unAllocated = fileStore.getUnallocatedSpace();
    long usable = fileStore.getUsableSpace();
}

Обратите внимание, что все возвращаемые значения находятся в байтах. Мы можем конвертировать в подходящие единицы, а также вычислять другую информацию, такую ​​как используемое пространство, используя базовую арифметику.

Разница между нераспределенным пространством и используемым пространством заключается в доступности для JVM.

Используемое пространство — это пространство, доступное для JVM, а нераспределенное пространство — это доступное пространство с точки зрения базовой файловой системы. Поэтому полезное пространство иногда может быть меньше нераспределенного пространства.

4. Атрибуты владельца файла

Для проверки информации о владельце файла мы используем интерфейс FileOwnerAttributeView. Это дает нам высокоуровневое представление информации о владении.

Мы можем создать объект FileOwnerAttributeView следующим образом:

Path path = Paths.get(HOME);
FileOwnerAttributeView ownerView = Files.getFileAttributeView(
  attribPath, FileOwnerAttributeView.class);

Чтобы получить владельца файла из приведенного выше представления:

UserPrincipal owner = ownerView.getOwner();

На самом деле мы ничего не можем сделать программно с указанным выше объектом, кроме получения имени владельца для какой-либо другой произвольной цели:

String ownerName = owner.toString();

5. Определяемые пользователем атрибуты файла

Существуют сценарии, когда атрибуты файла, определенные в файловой системе, недостаточны для ваших нужд. Если вы столкнетесь с таким случаем и вам потребуется установить свои собственные атрибуты в файле, вам пригодится интерфейс UserDefinedFileAttributeView:

Path path = Paths.get("somefile");
UserDefinedFileAttributeView userDefView = Files.getFileAttributeView(
  attribPath, UserDefinedFileAttributeView.class);

Чтобы получить список определенных пользователем атрибутов, уже определенных для файла, представленного выше представление:

List<String> attribList = userDefView.list();

Чтобы установить пользовательский атрибут в файле, мы используем следующую идиому:

String name = "attrName";
String value = "attrValue";
userDefView.write(name, Charset.defaultCharset().encode(value));

Когда вам нужно получить доступ к определенным пользователем атрибутам, вы можете просмотреть список атрибутов, возвращаемый функцией представление и проверить их, используя следующую идиому:

ByteBuffer attrValue = ByteBuffer.allocate(userView.size(attrName));
userDefView.read(attribName, attribValue);
attrValue.flip();
String attrValue = Charset.defaultCharset().decode(attrValue).toString();

Чтобы удалить определяемый пользователем атрибут из файла, мы просто вызываем API удаления представления:

userDefView.delete(attrName);

6. Заключение

В этом В статье мы рассмотрели некоторые из менее часто используемых функций, доступных в API-интерфейсах файловой системы Java 7 NIO.2, в частности, API-интерфейсы файловых атрибутов.

Полный исходный код примеров, используемых в этой статье, доступен в проекте Github.