File.mkdir или mkdirs return false - причина?

Почему file.mkdir возвращает false?

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

Мои вопросы:

  • Как найти точную причину возврата false?
  • Если безопасность/разрешения являются причиной, то почему SecurityException не выбрасывается?

Ответ 1

Если безопасность/разрешения являются причиной, то почему не генерируется SecurityException (что упоминается в javadoc)?

SecurityException генерируется, когда у вас нет разрешения уровня JVM на что-либо, а не на уровне ОС

Есть ли способ найти точную причину возврата false?

Нет, AFAIK. Единственный способ узнать это - самостоятельно проверить разрешения для каталога, убедиться, что он не существует, прежде чем вызывать их, проверить, существует ли родительский каталог и т.д.

Однако, если вы используете Java 7 или выше, вы можете использовать вместо этого NIO для создания каталога. В частности, Files.createDirectory:

File dir = new File("mydir");
Files.createDirectory(dir.toPath());

Если вы хотите использовать NIO полностью без использования java.io.File, вы можете использовать Paths.get для создания Path:

Path dir = Paths.get("mydir");
Files.createDirectory(dir);

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

Это верно для большинства методов в Files, поэтому рекомендуется использовать его, а не методы в классе File.

Ответ 2

mkdir и mkdirs возвращают false, если каталог уже существует, поэтому это может быть одной из причин отказа.

Если вы используете Java 7, вы можете использовать класс Files. Он генерирует IOException при ошибке с довольно хорошими описаниями.

Files.createDirectory(file.toPath());

Ответ 3

  • Нет, нет способа найти точную причину mkdirs() возвращает false, по крайней мере, не изнутри Java, так как это, вероятно, зависит от ОС.

  • A SecurityException вызывается, если есть нарушение безопасности в методах SecurityManager checkRead() и checkWrite(). Исключение не выбрасывается, если есть проблема с разрешениями ОС.


Кроме того, обратите внимание, что если вы вызываете File.mkdir(), а родительский каталог не существует, mkdir() возвращает false. Однако вызов File.mkdirs() приведет к созданию несуществующих родительских каталогов.

Ответ 4

Вот кое-что специфичное для Windows: в моем случае метод file.mkdir() не NoSuchFileException с NoSuchFileException потому что я пытался создать вложенную структуру каталогов напрямую (например, results\results_ddMMyyyy без предварительного создания каталога results) в Windows.

Тем не менее, точно такой же код работал на моем Mac, т.е. такого исключения не было на Mac, и промежуточный каталог results неявно создавался методом file.mkdir().

Надеюсь, это поможет кому-то в будущем.

Ответ 5

У меня был сбой mkdirs() в Windows на пути UNC. Код выглядит так:

public File getOldDirectoryPath(String root, String name)
{   
    File fulldir = new File(root, name)
    boolean created = false

    int retry = 0
    while (!created) {
        retry++
        if (!(created = fulldir.exists())) {
            if (20 == retry) break 
            if (!fulldir.mkdirs()) {
                sleep(100)
                fulldir = new File(root, name)
            }
        }
    }
    return fulldir.exists() ? fulldir : null
}

Похоже, что происходит какое-то кеширование, в случае если с существующим() возвращается ложное (не существует), но в файловой системе происходит сбой mkdir, поскольку он существует. Повторное создание записи File() или увеличение времени ожидания не имело значения.

Я обнаружил плагин наasticsearch, чтобы исправить проблему SMB в Windows. Исследуя решение, он использует nio.file вместо io.File. Переписывание функции устранило проблему:

public File getDirectoryPath(String root, String name)
{   
    Path fulldir = Paths.get(root, name)
    boolean created = false

    int retry = 0
    while (!created) {
        retry++
        if (!(created = Files.isDirectory(fulldir))) {
            if (20 == retry) break
            try {
                Files.createDirectories(fulldir)
            } catch (Throwable thx) {
                // error handling
            }
        }
    }
    return fulldir.toFile()
}

createDirectories() иногда завершается ошибкой, но восстанавливает, где mkdirs() не делает.