В настоящее время множество приложений создают файлы или каталоги для самых разных целей. Будь то создание отчета, экспорт части конфигурации или просто сохранение некоторых данных, важно уметь справляться с этими задачами. Создание файлов и каталогов — одна из наиболее часто используемых функций при работе с файловой системой. Эта часть библиотеки подверглась значительной модернизации. Обновления в этой области включают гарантию атомарности определенных операций, создание файлов и каталогов с предустановленными атрибутами файлов, оптимизацию производительности, а также введение иерархии исключений, которая заменила методы boolean
возврата из предыдущих версий библиотеки ввода-вывода.
Методы проверки
Прежде чем мы перейдем к какому-либо коду или объяснению, позвольте мне сделать шаг назад и сосредоточиться на чем-то, что будет иметь важное значение не только для этого поста, но и для ряда постов в будущем. Мне важно знать несколько методов, которые обычно называются методами проверки. Методы проверки включают все те методы, которые используются для выполнения различных проверок перед вызовом действительного кода манипулирования файловой системой. Для удобства все они в классе java.nio.file.Files
. Использование этих методов поможет вам предотвратить непредвиденное поведение вашего приложения. Поскольку эти методы действительно просты, я пропущу примеры, посвященные им, и вместо этого буду использовать их в следующих примерах.
Название метода | Описание |
---|---|
exists(Path path, LinkOption... options) |
Проверяет, существует ли файл. |
isExecutable(Path path) |
Проверяет, является ли файл исполняемым. |
isHidden(Path path) |
Сообщает, считается ли файл скрытым. |
isReadable(Path path) |
Проверяет, доступен ли файл для чтения. |
isRegularFile(Path path, LinkOption... options) |
Проверяет, является ли файл обычным файлом с непрозрачным содержимым. |
isSameFile(Path path, Path path2) |
Проверяет, находятся ли два пути в одном и том же файле. |
isWritable(Path path) |
Проверяет, доступен ли файл для записи. |
notExists(Path path, LinkOption... options) |
Проверяет, не существует ли файл, расположенный по этому пути. |
Создание нового каталога
Одним из наиболее важных применений класса Files
является создание новых каталогов с использованием метода createDirectory
. Создание каталога довольно простой и понятный процесс, поэтому объяснять особо нечего. Как обычно, всегда полезно использовать метод проверки, exists
классе Files
для обеспечения возможности создания каталога с заданным путем, а также для предотвращения исключения FileAlreadyExistsException
. Вся ситуация представлена в следующем фрагменте кода:
1
2
3
4
5
6
7
8
9
|
Path newDirectoryPath = Paths.get( "/home/jstas/directory" ); if (!Files.exists(newDirectoryPath)) { try { Files.createDirectory(newDirectoryPath); } catch (IOException e) { System.err.println(e); } } |
Пример кода довольно прост — он создает каталог с указанным путем, если никакой другой элемент файловой системы не находится на указанном пути. Если нам нужно создать целую иерархию каталогов, то нам нужно переключиться на метод createDirectories
который ведет себя аналогично и создает целую иерархию, определяемую экземпляром пути. Поскольку каталог является типом файла, мы можем устанавливать свои собственные метаданные ( атрибуты файла ). Мы не только можем это сделать, мы даже можем заранее создать определение метаданных и создать каталог с начальными атрибутами файла в элементарной операции, предотвращающей любые несоответствия на этом пути. Как упоминалось в моей предыдущей статье, существует два поддерживаемых стандарта для управления разрешениями файловой системы: POSIX и ACL.
Разрешения файла POSIX
Во-первых, давайте посмотрим, как мы можем управлять разрешениями файловой системы в POSIX-совместимых системах, таких как системы на базе Linux и Mac OS. Благодаря тому, что разрешения для файлов POSIX довольно просты для понимания, создатели библиотек предоставляют нам удобные инструменты, такие как прямой перевод из строкового представления в набор PosixFilePermission
или инструмент преобразования для преобразования указанного набора в объект FileAttribute
. Это не единственный способ создания объекта FileAttribute
как мы увидим в следующей главе.
Возвращаясь к приведенному примеру, давайте рассмотрим следующий код. Используя fromString
метод fromString
класса PosixFilePermissions
мы можем создать набор элементов PosixFilePermission
. Теперь необходимо создать экземпляр FileAttribute
для передачи в метод createDirectory
который создает наш тестовый каталог. Давайте посмотрим на следующий фрагмент кода:
01
02
03
04
05
06
07
08
09
10
11
12
|
Path newDirectoryPath = Paths.get( "/home/jstas/testPosix" ); if (!Files.exists(newDirectoryPath)) { Set<PosixFilePermission> permissions = PosixFilePermissions.fromString( "r-xr-----" ); FileAttribute<Set<PosixFilePermission>> fileAttributes = PosixFilePermissions.asFileAttribute(permissions); try { Files.createDirectory(newDirectoryPath, fileAttributes); } catch (IOException e) { System.err.println(e); } } |
Легко проверить, правильно ли были установлены наши разрешения. Вы можете либо прочитать атрибуты файла непосредственно из кода Java, как я представил в статье Атрибуты файла, либо сделать это вручную. Я использовал системный терминал, чтобы проверить их следующим выводом:
1
|
dr-xr-----. 2 jstas jstas 4096 Jan 5 13:34 testPosix |
Права доступа к файлу ACL
Все становится немного сложнее при управлении разрешениями файловой системы в ACL-совместимых системах, таких как Windows (NT, 2000, XP и новее). Списки ACL могут быть довольно сложными и надежными, поэтому здесь нет ярлыков, как с разрешениями для файлов POSIX. Ключевым моментом здесь является использование анонимного определения класса на основе интерфейса FileAttribute
. Этот интерфейс определяет только два метода: name
возвращает имя атрибута файла, а value
возвращает значение этого атрибута. При работе с ACL интересующий нас атрибут называется «acl: acl» . Метод value
просто возвращает список созданных записей ACL.
Давайте посмотрим, что скрыто внутри записи ACL и как создать экземпляр AclEntry
. Прежде всего, запись ACL состоит из нескольких объектов:
- Флаги
- Компонент flags представляет собой набор флагов для указания того, как записи наследуются и распространяются
- Значения:
DIRECTORY_INHERIT
,FILE_INHERIT
,INHERIT_ONLY
,NO_PROPAGATE_INHERIT
- права доступа
- Компонент разрешений представляет собой набор разрешений
- Значения:
APPEND_DATA
,DELETE
,DELETE_CHILD
,EXECUTE
,READ_ACL
,READ_ATTRIBUTES
,READ_DATA
,READ_NAMED_ATTRS
,
SYNCHRONIZE
,WRITE_ACL
,WRITE_ATTRIBUTES
,WRITE_DATA
,WRITE_NAMED_ATTRS
,WRITE_OWNER
- Тип
- принципал
- Основной компонент, иногда называемый компонентом who, представляет собой
UserPrincipal
соответствующий идентификатору, который запись предоставляет или запрещает доступ - Значения, полученные с помощью
UserPrincipalLookupService
- Основной компонент, иногда называемый компонентом who, представляет собой
Учитывая сложность одной записи ACL, создатели библиотеки NIO.2 увидели очень подходящего кандидата для реализации шаблона компоновщика. Посетите следующую страницу для получения дополнительной информации о шаблонах проектирования и шаблонах сборки . Таким образом, реализация выбирает соответствующие флаги и разрешения, связывает их с пользователем и устанавливает тип записи. Пожалуйста, изучите следующий фрагмент кода, чтобы ознакомиться с разрешениями ACL:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
Path newDirectoryPath = Paths.get( "c:" , "testACL" ); if (!Files.exists(newDirectoryPath)) { FileAttribute<List<AclEntry>> fileAttributes = new FileAttribute<List<AclEntry>>() { @Override public List<AclEntry> value() { // lookup user principal FileSystem fileSystem = FileSystems.getDefault(); UserPrincipalLookupService userPrincipalLookupService = fileSystem.getUserPrincipalLookupService(); UserPrincipal userPrincipal = null ; try { userPrincipal = userPrincipalLookupService.lookupPrincipalByName( "JStas" ); } catch (IOException e) { throw new RuntimeException(e); } // select ACL flags Set<AclEntryFlag> flags = EnumSet.of(AclEntryFlag.FILE_INHERIT, AclEntryFlag.DIRECTORY_INHERIT); // select ACL permission Set<AclEntryPermission> permissions = EnumSet.of(AclEntryPermission.READ_DATA, AclEntryPermission.WRITE_DATA, AclEntryPermission.EXECUTE); // build ACL entry Builder builder = AclEntry.newBuilder(); builder.setFlags(flags); builder.setPermissions(permissions); builder.setPrincipal(userPrincipal); builder.setType(AclEntryType.DENY); AclEntry entry = builder.build(); List<AclEntry> aclEntryList = new ArrayList<>(); aclEntryList.add(entry); return aclEntryList; } @Override public String name() { return "acl:acl" ; } }; try { Files.createDirectory(newDirectoryPath, fileAttributes); } catch (IOException e) { System.err.println(e); } } |
Чтобы проверить успешное создание каталога и его атрибутов файла в Windows 7, выберите вкладку «Безопасность» в свойствах данной папки и нажмите «Дополнительно». Ваша вновь созданная запись должна быть перечислена в представленной таблице с подробным представлением, подобным этому:
Создание нового файла
Основная часть любого кода, связанного с файловой системой, обычно включает в себя код, который создает один или несколько файлов. Для создания файла нам нужно снова использовать класс Files
и вызвать метод createFile
. Точно так же как каталог, файл может быть создан с начальными атрибутами файла, и применяются те же ограничения. Сказав, что я не собираюсь демонстрировать работу с атрибутами файлов, так как она такая же, как в примере каталога. Еще раз, это действительно простой метод, без зацепок, поэтому все представлено в следующем примере:
1
2
3
4
5
6
7
8
9
|
Path newFilePath = Paths.get( "C:" , "a.txt" ); if (!Files.exists(newFilePath)) { try { Files.createFile(newFilePath); } catch (IOException e) { System.err.println(e); } } |
Пожалуйста, обратите внимание на использование метода проверки exists
который предотвращает FileAlreadyExistsException
.
Ссылка: | Создание файлов и каталогов в NIO.2 от нашего партнера JCG Якуба Стаса в блоге |