Перейти к основному содержимому

Проверьте, существует ли файл или каталог в Java

· 4 мин. чтения

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 .