Обнаружение причины сбоя File.mkdirs()

Если я вызываю один из методов File.mkdir() или File.mkdirs() в Java и возвращает false, есть ли способ узнать, почему каталог не был создан?

Ответ 1

Не совсем, нет. Если a SecurityException НЕ выбрасывается, то наиболее вероятной причиной является опечатка в пути, то есть вы случайно указали родительский путь к новым каталогам, которые каким-то образом недействительны.

Я не предполагаю, что вы его завернули в блок try { ... } catch (Exception e), где вы не понимаете, что бросается SecurityException, потому что вы ловите предка SecurityException, не так ли?

Если у вас есть высокая убежденность в том, что все выглядит правильно, и все еще не удается, я полагаю, вы могли бы просто поставить его в цикл, чтобы повторить, скажем, три раза. Если он по-прежнему не работает, и в зависимости от вашего приложения вы можете поднять какое-то предупреждение на уровне пользовательского интерфейса или зарегистрировать ошибку в файле журнала (при условии, что вы можете записать на нее).

Я полагаю, что возможно, что некоторая более глубокая проблема ввода-вывода не позволяет ему работать, но помимо простого уведомления пользователя о сбое, вы не можете (или действительно должны) делать это на уровне приложения. Если что-то глубже в I/O неправильно, это скорее проблема с системой/аппаратным обеспечением/ОС, или что-то совершенно неудобное, что вы не контролируете, как сбои в подсистеме/службе.

... и если это произойдет, то ответственность IT-специалиста исправить, а не ваше приложение. Если, конечно, ваше приложение каким-то образом не приведет к сбою.

Ответ 2

У меня был сбой 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() не делает.