Руководство по API атрибутов файлов NIO2

Руководство по API-интерфейсам атрибутов файлов NIO2

1. обзор

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

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

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

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);
}

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

@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));
}

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

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

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

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

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

accessed.toString();

Который печатает что-то полезное в формате времени ISO:

2016-11-24T07:52:53.376Z

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

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

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

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

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

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

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

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

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

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

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

long total = store.getTotalSpace();

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

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

Мы менее склонны следовать этому подходу, чем следующий.

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

Iterable fileStores = FileSystems.getDefault().getFileStores();

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

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

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

The difference between unallocated space and usable space доступен для 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 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 project.