1. Обзор
В этом кратком руководстве мы познакомимся с различными способами проверки существования файла или каталога.
Сначала мы начнем с современных API-интерфейсов NIO, а затем рассмотрим устаревшие подходы к вводу-выводу.
2. Использование java.nio.file.Files
Чтобы проверить, существует ли файл или каталог, мы можем использовать метод Files.exists (Path)
. Как видно из сигнатуры метода, мы должны сначала получить путь
к нужному файлу или каталогу. Затем мы можем передать этот путь
в метод Files.exists(Path)
:
Path path = Paths.get("does-not-exist.txt");
assertFalse(Files.exists(path));
Поскольку файл не существует, он возвращает false
. Также стоит упомянуть, что если метод Files.exists(Path)
встречает IOException
, он также возвращает false
.
С другой стороны, когда данный файл существует, он вернет true
, как и ожидалось:
Path tempFile = Files.createTempFile("foreach", "exist-article");
assertTrue(Files.exists(tempFile));
Здесь мы создаем временный файл, а затем вызываем метод Files.exists(Path)
.
Это работает даже для каталогов :
Path tempDirectory = Files.createTempDirectory("foreach-exists");
assertTrue(Files.exists(tempDirectory));
Если мы специально хотим знать, существует ли файл или каталог, мы также можем использовать методы Files.isDirectory(Path)
или Files.isRegularFile(Path)
:
assertTrue(Files.isDirectory(tempDirectory));
assertFalse(Files.isDirectory(tempFile));
assertTrue(Files.isRegularFile(tempFile));
Существует также метод notExists(Path)
, который возвращает true
, если заданный путь
не существует:
assertFalse(Files.notExists(tempDirectory));
Иногда Files.exists(Path)
возвращает false
, потому что у нас нет необходимых прав доступа к файлам . В таких сценариях мы можем использовать метод Files.isReadable(Path)
, чтобы убедиться, что файл действительно доступен для чтения текущему пользователю:
assertTrue(Files.isReadable(tempFile));
assertFalse(Files.isReadable(Paths.get("/root/.bashrc")));
2.1. Символические ссылки
По умолчанию метод Files.exists(Path)
следует символическим ссылкам . Если файл A
имеет символическую ссылку на файл B
, то метод Files.exists(A)
возвращает значение true
тогда и только тогда, когда файл B
уже существует:
Path target = Files.createTempFile("foreach", "target");
Path symbol = Paths.get("test-link-" + ThreadLocalRandom.current().nextInt());
Path symbolicLink = Files.createSymbolicLink(symbol, target);
assertTrue(Files.exists(symbolicLink));
Теперь, если мы удалим цель ссылки, Files.exists(Path)
вернет false
:
Files.deleteIfExists(target);
assertFalse(Files.exists(symbolicLink));
Поскольку цель ссылки больше не существует, переход по ссылке ни к чему не приведет, а Files.exists(Path)
вернет false
.
Можно даже не переходить по символическим ссылкам, передав соответствующий LinkOption
в качестве второго аргумента:
assertTrue(Files.exists(symbolicLink, LinkOption.NOFOLLOW_LINKS));
Поскольку сама ссылка существует, метод Files.exists(Path)
возвращает значение true.
Кроме того, мы можем проверить, является ли путь
символической ссылкой, используя метод Files.isSymbolicLink(Path)
:
assertTrue(Files.isSymbolicLink(symbolicLink));
assertFalse(Files.isSymbolicLink(target));
3. Использование java.io.File
Если мы используем Java 7 или более новую версию Java, настоятельно рекомендуется использовать современные API-интерфейсы Java NIO для таких требований .
Однако, чтобы убедиться, что файл или каталог существует в устаревшем мире ввода-вывода Java, мы можем вызвать метод exists ()
для экземпляров File :
assertFalse(new File("invalid").exists());
Если файл или каталог уже существует, он вернет true
:
Path tempFilePath = Files.createTempFile("foreach", "exist-io");
Path tempDirectoryPath = Files.createTempDirectory("foreach-exists-io");
File tempFile = new File(tempFilePath.toString());
File tempDirectory = new File(tempDirectoryPath.toString());
assertTrue(tempFile.exists());
assertTrue(tempDirectory.exists());
Как показано выше, метод exists()
не заботится о том, файл это или каталог. Поэтому, пока он существует, он будет возвращать true
.
Однако метод isFile()
возвращает true
, если указанный путь является существующим файлом:
assertTrue(tempFile.isFile());
assertFalse(tempDirectory.isFile());
Точно так же метод isDirectory()
возвращает true
, если указанный путь является существующим каталогом:
assertTrue(tempDirectory.isDirectory());
assertFalse(tempFile.isDirectory());
Наконец, метод canRead()
возвращает true
, если файл доступен для чтения:
assertTrue(tempFile.canRead());
assertFalse(new File("/root/.bashrc").canRead());
Когда он возвращает false
, файл либо не существует, либо текущий пользователь не имеет разрешения на чтение файла.
4. Вывод
В этом кратком руководстве мы увидели, как убедиться, что файл или каталог существует в Java. Попутно мы говорили о современном NIO и устаревших API-интерфейсах ввода-вывода. Кроме того, мы увидели, как NIO API обрабатывает символические ссылки.
Как обычно, все примеры доступны на GitHub .