Mkdir: примеры (JAVA)

Создание каталогов в Java: обзор способов
Раздел: Ввод-вывод (I/O) файловый
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
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
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
java.nio.file.Path tmpDir = java.nio.file.Files.createTempDirectory("app-");
System.out.println(tmpDir);
// ... работа с каталогом ...
// Удаление (рекурсивное) через walk()
/tmp/app-1234567890
Пример java
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 для упрощения и более подробной диагностики.

Пример java
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 и проверке возвращаемых исключений.

джава mkdir function comments

En
Mkdir Creates the directory named by this abstract pathname