Mkdir: примеры (JAVA)
mkdir: booleanОписание
В Java под словом mkdir обычно понимают операции создания каталога. В классической библиотеке имеются несколько API для этой задачи: java.io.File.mkdir(), java.io.File.mkdirs(), а также современный набор из пакета java.nio.file - в первую очередь Files.createDirectory(Path, FileAttribute<?>...) и Files.createDirectories(Path, FileAttribute<?>...).
Краткая характеристика методов:
- File.mkdir()
- Сигнатура:
public boolean mkdir(). - Аргументы: нет (вызывается на объекте File, представляющем путь к каталогу).
- Возвращаемое значение:
true- каталог создан;false- каталог не создан (например, родительские каталоги отсутствуют, или уже существует файл с таким именем, или нет прав). - Исключения: может бросать
SecurityExceptionпри отказе безопасности, не бросает IOException.
- Сигнатура:
- File.mkdirs()
- Сигнатура:
public boolean mkdirs(). - Аргументы: нет.
- Возвращаемое значение:
true- каталоги созданы (включая необходимые родительские);false- создание не выполнено. - Поведение: пытается создать всю структуру директорий по пути.
- Сигнатура:
- Files.createDirectory(Path, FileAttribute...)
- Сигнатура:
public static Path createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException. - Аргументы:
Path- путь к создаваемому каталогу; опционально - массив атрибутов для установки сразу при создании (например, POSIX-права на UNIX). - Возвращаемое значение:
Pathу вновь созданного каталога. - Исключения: бросает
FileAlreadyExistsException, если объект существует,IOExceptionпри ошибках ввода-вывода иSecurityExceptionпри отказе безопасности.
- Сигнатура:
- Files.createDirectories(Path, FileAttribute...)
- Сигнатура:
public static Path createDirectories(Path dir, FileAttribute<?>... attrs) throws IOException. - Поведение: создает все отсутствующие родительские каталоги; если каталог уже существует, исключение не бросается и возвращается путь.
- Сигнатура:
Выбор между вариантами зависит от задач: нужна ли информации об исключениях и атомарность (предпочтение Files), требуется ли создание всех родителей (использовать mkdirs или Files.createDirectories), или достаточно простого булевого результата (File.mkdir).
Короткие примеры
Примеры показывают поведение на простых сценариях. Код и ожидаемый результат приведены рядом.
File.mkdir при отсутствии родителя
java.io.File f = new java.io.File("tmp/a");
boolean ok = f.mkdir();
System.out.println(ok);
false
File.mkdirs создает всю структуру
java.io.File f2 = new java.io.File("tmp/a/b");
boolean ok2 = f2.mkdirs();
System.out.println(ok2);
// Повторный вызов на существующем пути
true false
Files.createDirectory при существующем каталоге
java.nio.file.Path p = java.nio.file.Paths.get("tmp/ex1");
try {
java.nio.file.Files.createDirectory(p);
System.out.println("created");
} catch (java.nio.file.FileAlreadyExistsException e) {
System.out.println("exists");
} catch (java.io.IOException e) {
System.out.println("io error");
}
created // при повторном запуске: exists
Files.createDirectories создает при отсутствии родителей и тихо пропускает наличие каталога
java.nio.file.Path p2 = java.nio.file.Paths.get("tmp/x/y/z");
java.nio.file.Files.createDirectories(p2);
System.out.println(java.nio.file.Files.isDirectory(p2));
true
Files.createDirectory с установкой POSIX прав (на UNIX-системах)
java.nio.file.Path p3 = java.nio.file.Paths.get("tmp/posixDir");
java.nio.file.attribute.PosixFilePermission perm = java.nio.file.attribute.PosixFilePermission.OWNER_READ;
java.nio.file.attribute.PosixFilePermission perm2 = java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
java.util.Set<java.nio.file.attribute.PosixFilePermission> perms = java.util.EnumSet.of(perm, perm2);
java.nio.file.attribute.FileAttribute<java.util.Set<java.nio.file.attribute.PosixFilePermission>> attr =
java.nio.file.attribute.PosixFilePermissions.asFileAttribute(perms);
java.nio.file.Files.createDirectory(p3, attr);
System.out.println(java.nio.file.Files.getPosixFilePermissions(p3));
[OWNER_READ, OWNER_WRITE]
Похожие API в Java
Несколько вариантов с отличиями:
- File.mkdir() и File.mkdirs() - устаревающий по духу, но простой API, возвращает boolean без подробных исключений.
- Files.createDirectory - современный подход с подробной информацией об ошибке через исключения и поддержкой передачи атрибутов при создании.
- Files.createDirectories - отличается тем, что создает отсутствующие родительские каталоги и не рассматривает уже существующий каталог как ошибку.
- Apache Commons IO: FileUtils.forceMkdir(File) - удобная утилита, бросает IOException при ошибке и делает родительские каталоги при необходимости; подходит в приложениях, где уже используется Commons IO.
Выбор обычно строится на предпочтении четкой обработки ошибок и переносимости. Для новых проектов чаще рекомендуется Files API, при простых скриптовых задачах может хватать File.mkdirs().
Альтернативы в других языках
Краткие примеры и отличие от Java:
- PHP -
mkdirимеет флаг для рекурсивного создания и право доступа.
// PHP
mkdir('tmp/php/a', 0755, true);
echo is_dir('tmp/php/a') ? 'ok' : 'no';
ok
Отличие: PHP возвращает boolean и использует mode и флаг recursive.
- JavaScript (Node.js) -
fs.mkdirSync(path, { recursive: true })или асинхронно с колбэком/промисом.
// Node.js
const fs = require('fs');
fs.mkdirSync('tmp/node/a', { recursive: true });
console.log(fs.existsSync('tmp/node/a'));
true
Отличие: Node.js поддерживает асинхронность и опции в объекте, возвращает ошибку через исключение/колбэк.
- Python -
os.mkdir(path)иos.makedirs(path, exist_ok=False).
# Python
import os
os.makedirs('tmp/py/a', exist_ok=True)
print(os.path.isdir('tmp/py/a'))
True
Отличие: флаг exist_ok управляет поведением при существующем каталоге.
- C# -
System.IO.Directory.CreateDirectory(path)создает все недостающие каталоги и возвращает объект DirectoryInfo.
// C#
var dir = System.IO.Directory.CreateDirectory("tmp/cs/a");
Console.WriteLine(dir.Exists);
True
Отличие: CreateDirectory всегда создает родителей и не бросает ошибку, если каталог уже существует.
- Go -
os.Mkdir(path, perm)иos.MkdirAll(path, perm).
// Go
package main
import (
"fmt"
"os"
)
func main() {
os.MkdirAll("tmp/go/a", 0755)
info, _ := os.Stat("tmp/go/a")
fmt.Println(info.IsDir())
}
true
Отличие: явное указание прав и разделение на одиночное/рекурсивное создание.
- Kotlin - использует те же API, что и Java, например
java.nio.file.Files.createDirectoriesилиFile.mkdirs().
В большинстве языков присутствуют две модели: возвращение булева результата или бросание исключения/ошибки. Java предлагает оба подхода через разные API.
Типичные ошибки
Наиболее часто встречающиеся проблемы при создании каталогов:
- Неправильное поведение
File.mkdir(): возвращаетсяfalseпри отсутствии родителя. Пример:
java.io.File f = new java.io.File("no_parent/dir");
System.out.println(f.mkdir());
false
- Исключение
FileAlreadyExistsExceptionпри использованииFiles.createDirectoryесли объект уже существует как файл или каталог.
java.nio.file.Path p = java.nio.file.Paths.get("tmp/existfile");
java.nio.file.Files.write(p, new byte[]{1});
try {
java.nio.file.Files.createDirectory(p);
} catch (Exception e) {
System.out.println(e.getClass().getSimpleName());
}
FileAlreadyExistsException
- Отказ в доступе:
SecurityExceptionилиIOExceptionпри недостаточных правах. Пример имитируется отказом безопасности через SecurityManager в старых JVM, в современных окружениях чаще встречается IOException. - Гонка между потоками или процессами: проверка существования до создания может привести к ошибке создания, если другой процесс создал путь одновременно. Рекомендуется полагаться на исключения
Files.createDirectoryи обрабатыватьFileAlreadyExistsException.
Изменения в API
Ключевое изменение состоялось в Java 7 с введением NIO.2 (пакет java.nio.file). Там появились Path и Files.createDirectory/createDirectories, которые обеспечивают более детальную обработку ошибок и возможность указать атрибуты при создании. С тех пор интерфейсы для создания каталогов сохраняются стабильными и совместимыми назад. Мелкие улучшения касались документации и поведения при атомарности на конкретных файловых системах, но сигнатуры методов в основных релизах не изменялись.
Расширенные примеры
Несколько более сложных сценариев с пояснениями.
1) Создание каталога с обработкой гонки процессов. Подход: попытаться создать и при ошибке проверить, действительно ли каталог теперь существует.
java.nio.file.Path p = java.nio.file.Paths.get("tmp/concurrent");
try {
java.nio.file.Files.createDirectory(p);
System.out.println("created");
} catch (java.nio.file.FileAlreadyExistsException e) {
System.out.println(java.nio.file.Files.isDirectory(p) ? "already directory" : "exists but not directory");
} catch (java.io.IOException e) {
System.out.println("io error");
}
created // или при одновременном создании: already directory
Пояснение: это предотвращает ошибку «check-then-act» и корректно обрабатывает ситуацию, когда другой процесс создал путь между проверкой и созданием.
2) Создание каталога с заданием POSIX прав и проверкой поддерживаемости этой функции на платформе.
java.nio.file.Path p2 = java.nio.file.Paths.get("tmp/secure");
if (java.nio.file.FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) {
java.util.Set<java.nio.file.attribute.PosixFilePermission> perms =
java.util.EnumSet.of(java.nio.file.attribute.PosixFilePermission.OWNER_READ,
java.nio.file.attribute.PosixFilePermission.OWNER_WRITE);
java.nio.file.attribute.FileAttribute<java.util.Set<java.nio.file.attribute.PosixFilePermission>> attr =
java.nio.file.attribute.PosixFilePermissions.asFileAttribute(perms);
java.nio.file.Files.createDirectories(p2, attr);
System.out.println(java.nio.file.Files.getPosixFilePermissions(p2));
} else {
System.out.println("posix not supported");
}
[OWNER_READ, OWNER_WRITE] // или: posix not supported
Пояснение: указание атрибутов при создании полезно для предотвращения промежуточного состояния с неверными правами.
3) Создание временного каталога для работы и его гарантированное удаление.
java.nio.file.Path tmpDir = java.nio.file.Files.createTempDirectory("app-");
System.out.println(tmpDir);
// ... работа с каталогом ...
// Удаление (рекурсивное) через walk()
/tmp/app-1234567890
java.nio.file.Files.walk(tmpDir)
.sorted(java.util.Comparator.reverseOrder())
.map(java.nio.file.Path::toFile)
.forEach(java.io.File::delete);
// файлы удалены
Пояснение: createTempDirectory создаёт уникальный временный каталог; удаление рекурсивно требует обхода дерева.
4) Использование Apache Commons IO для упрощения и более подробной диагностики.
org.apache.commons.io.FileUtils.forceMkdir(new java.io.File("tmp/commons/a"));
System.out.println(new java.io.File("tmp/commons/a").isDirectory());
true
Пояснение: FileUtils.forceMkdir бросает IOException при ошибке, что упрощает обработку в коде, где используется исключительная логика.
5) Пример с Windows ACL можно реализовать через AclFileAttributeView на поддерживаемой файловой системе, но код требует сложных структур и прав. В современных приложениях предпочтение отдается абстракции Files и проверке возвращаемых исключений.