«1. Обзор

Класс java.io.File имеет три метода — getPath(), getAbsolutePath() и getCanonicalPath() — для получения пути к файловой системе.

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

2. Определения методов и примеры

Давайте начнем с определения трех методов, а также примеров, основанных на наличии следующей структуры каталогов в домашнем каталоге пользователя:

|-- baeldung
    |-- baeldung.txt
    |-- foo
    |   |-- foo-one.txt
    |   \-- foo-two.txt
    \-- bar
        |-- bar-one.txt
        |-- bar-two.txt
        \-- baz
            |-- baz-one.txt
            \-- baz-two.txt

2.1. getPath()

Проще говоря, getPath() возвращает строковое представление абстрактного пути к файлу. По сути, это путь, передаваемый конструктору File.

Таким образом, если объект File был создан с использованием относительного пути, возвращаемое значение из метода getPath() также будет относительным путем.

Если мы вызовем следующий код из каталога {user.home}/baeldung:

File file = new File("foo/foo-one.txt");
String path = file.getPath();

Переменная пути будет иметь значение:

foo/foo-one.txt  // on Unix systems
foo\foo-one.txt  // on Windows systems

Обратите внимание, что для системы Windows имя- символ разделителя изменился с символа косой черты (/), который был передан конструктору, на символ обратной косой черты (\\). Это связано с тем, что возвращаемая строка всегда использует символ-разделитель имен по умолчанию для платформы.

2.2. getAbsolutePath()

Метод getAbsolutePath() возвращает путь к файлу после разрешения пути для текущего пользовательского каталога — это называется абсолютным путем. Итак, для нашего предыдущего примера file.getAbsolutePath() вернет:

/home/username/baeldung/foo/foo-one.txt     // on Unix systems
C:\Users\username\baeldung\foo\foo-one.txt  // on Windows systems

Этот метод разрешает только текущий каталог для относительного пути. Сокращенные представления (такие как «.» и «..» ) далее не разрешаются. Следовательно, когда мы выполняем следующий код из каталога {user.home}/baeldung:

File file = new File("bar/baz/../bar-one.txt");
String path = file.getAbsolutePath();

Значением пути переменной будет:

/home/username/baeldung/bar/baz/../bar-one.txt      // on Unix systems
C:\Users\username\baeldung\bar\baz\..\bar-one.txt   // on Windows systems

2.3. getCanonicalPath()

Метод getCanonicalPath() идет еще дальше и разрешает абсолютный путь, а также сокращенные или избыточные имена, такие как «.» и «..», в соответствии со структурой каталога. Он также разрешает символические ссылки в системах Unix и преобразует букву диска в стандартный регистр в системах Windows.

Итак, для предыдущего примера метод getCanonicalPath() вернет:

/home/username/baeldung/bar/bar-one.txt     // on Unix systems
C:\Users\username\baeldung\bar\bar-one.txt  // on Windows systems

Давайте рассмотрим другой пример. Учитывая текущий каталог как ${user.home}/baeldung и объект File, созданный с использованием параметра new File(“bar/baz/./baz-one.txt”), вывод для getCanonicalPath() будет:

/home/username/baeldung/bar/baz/baz-one.txt     // on Unix systems
C:\Users\username\baeldung\bar\baz\baz-one.txt  // on Windows Systems

Стоит отметить, что один файл в файловой системе может иметь бесконечное количество абсолютных путей, поскольку существует бесконечное количество способов использования сокращенных представлений. Однако канонический путь всегда будет уникальным, поскольку все такие представления разрешены.

В отличие от последних двух методов, getCanonicalPath() может генерировать исключение IOException, поскольку требует запросов к файловой системе.

Например, в системах Windows, если мы создадим объект File с одним из недопустимых символов, разрешение канонического пути вызовет исключение IOException:

new File("*").getCanonicalPath();

3. Вариант использования

Допустим, мы написание метода, который принимает объект File в качестве параметра и сохраняет его полное имя в базе данных. Мы не знаем, является ли путь относительным или содержит сокращения. В этом случае мы можем захотеть использовать getCanonicalPath().

Однако, поскольку getCanonicalPath() читает файловую систему, это сказывается на производительности. Если мы уверены, что нет избыточных имен или символических ссылок, а регистр букв дисков стандартизирован (при использовании ОС Windows), то мы должны предпочесть использовать getAbsoultePath().

4. Заключение

В этом кратком руководстве мы рассмотрели различия между тремя методами File для получения пути к файловой системе. Мы также показали вариант использования, когда один метод может быть предпочтительнее другого.

Тестовый класс Junit, демонстрирующий примеры из этой статьи, можно найти на GitHub.