Java: comprobar si existe un archivo o directorio

Verificar si existe un archivo o directorio es una operación simple e importante en muchas tareas. En este artículo, exploraremos las muchas formas diferentes que puede emplear para verificar si un archivo o directorio existe si es un enlace simbólico y los contratiempos de estos enfoques.

Introducción

Verificar si existe un archivo o directorio es una operación simple e importante en muchas tareas. Antes de acceder a un archivo, debemos verificar si existe para evitar una NullPointerException. Lo mismo ocurre con los directorios.

Si bien algunas funciones pueden crear un nuevo archivo/directorio si el solicitado no existe, esto puede ser lo contrario de lo que queremos. Si deseamos agregar más información a un archivo existente y el método pasa sin una advertencia, ya que crea el nuevo archivo que necesita, es posible que hayamos perdido alguna información sin darnos cuenta.

Aquí, tenemos una estructura simple:

1
2
3
4
02/13/2020  11:53 AM    <DIR>          directory
02/13/2020  11:55 AM    <SYMLINKD>     directory_link [directory]
02/13/2020  11:53 AM                 0 file.txt
02/13/2020  11:55 AM    <SYMLINK>      symlink.txt [file.txt]

Hay un archivo file.txt y un archivo symlink.txt. El archivo symlink.txt es un enlace simbólico al file.txt.

Del mismo modo, tenemos un directorio y un enlace simbólico a él: directory_link.

Comprobar si existe un archivo

Para trabajar con la clase Files, debe estar familiarizado con la clase Path. Files solo acepta objetos Path y no File.

Para los propósitos del tutorial, definiremos una instancia de File y Path para file.txt en nuestro directorio:

1
2
3
4
final static String location = "C:\\file.txt";

Path path = Paths.get(location);
File file = new File(location);

Archivos.existe()

Dicho esto, la primera forma en que podemos verificar si existe un archivo es a través de la clase Files:

1
2
3
4
5
// Check if file exists through a Path
System.out.println(Files.exists(path));

// Check if a file exists by converting File object to Path
System.out.println(Files.exists(file.toPath()));

Ejecutar este código nos dará:

1
2
true
true

Archivos.notExists()

Quizás se pregunte por qué existe el método notExists():

Si exists() devuelve true, eso significa que notExists() debería devolver false. Son complementos lógicos y A = !B, ¿verdad?

Bueno, ahí es donde muchos se equivocan. Si Files.exists() devuelve false, no tiene que significar que el archivo no existe.

También puede significar que la existencia del archivo no se puede verificar. En ese caso, tanto Files.exists() como Files.notExists() devolverían falso, ya que Java no puede determinar si el archivo existe o no.

Esto suele ocurrir si tiene un archivo que está bloqueado de forma que Java no pueda acceder a él. Imagina que tenemos un archivo que está bloqueado en nuestro directorio - lockedFile.txt:

file with denied permissions

Y si tratamos de verificar su existencia con:

1
2
System.out.println(Files.exists(path));
System.out.println(Files.notExists(path));

Nos recibirían con:

1
2
false
false

Existe, obviamente, pero Java no tiene permiso para confirmarlo en nuestro sistema, lo que genera resultados contradictorios.

Archivos.esArchivoRegular()

Además, podemos verificar si el archivo es un archivo normal (falso si es un directorio) a través del método isRegularFile():

1
System.out.println(Files.isRegularFile(path));

La salida es:

1
true

Archivo.esArchivo()

En lugar de usar la clase Files, también podemos realizar métodos en los propios objetos de archivo:

1
System.out.println(file.isFile());

Esto devuelve:

1
true

Archivo.existe()

Similar a la opción anterior, podemos ejecutar el método exists():

1
System.out.println(file.exists());

Y esto también devuelve:

1
true

La diferencia entre estos dos es que el primero verifica si es un archivo y el otro verifica si existe. En diferentes circunstancias, devolverían resultados diferentes.

Archivos bloqueados

Una cosa divertida a tener en cuenta es que si estás usando un Archivo para verificar su existencia, Java puede determinar si el archivo bloqueado anterior existe o no:

1
2
System.out.println(file.isFile());
System.out.println(file.exists());

Ejecutar este fragmento de código producirá:

1
2
true
true

Con esto, es evidente que el archivo bloqueado puede leerse utilizando la clase File en lugar de la clase auxiliar Files.

Comprobar si existe un directorio

Los directorios son esencialmente archivos, que pueden contener otros archivos. Esta es la razón por la que verificar si un directorio es un archivo devolverá verdadero. Sin embargo, si está comprobando si un directorio es un directorio (un tipo especial de archivo), obtendrá un resultado más preciso.

Esta vez, vamos a cambiar nuestra ubicación a:

1
final static String location = "C:\\directory";

Archivos.existe()

Nuevamente, al igual que en el primer ejemplo, podemos verificar si existe a través de:

1
System.out.println(Files.exists(path));

La salida es:

1
true

Archivos.isDirectory()

Si quisiéramos verificar si es específicamente un directorio, usaríamos:

1
System.out.println(Files.isDirectory(path));

Y la salida es:

1
true

Nota: Si el directorio no existe, el método isDirectory() devolverá falso. Se debe a la forma en que se nombra el método. Lo que hace es verificar si el archivo existe y si es un directorio, no solo el último. Un archivo no puede ser un directorio si no existe; por lo tanto, se devuelve falso.

También es posible que desee verificar si un archivo es solo un enlace simbólico. En ese caso, usarías la clase Files.

Cambiemos nuestra ubicación a:

1
final static String location = "C:\\symlink.txt";

Archivos.esEnlaceSimbólico()

Como de costumbre, la clase Files acepta una Ruta al archivo:

1
System.out.println(Files.isSymbolicLink(path));

Ejecutar esto produciría:

1
true

File.getCanonicalPath() frente a File.getAbsolutePath()

Otra forma de verificar un enlace simbólico es comparar los resultados de la ruta canónica y la ruta absoluta del archivo. Si son diferentes, lo más probable es que sea un enlace simbólico:

1
2
System.out.println(file.getCanonicalPath());
System.out.println(file.getAbsolutePath());

Dado que estamos buscando un enlace simbólico, y sabemos que lo es, estos deberían devolver un resultado diferente: una ruta symlink.txt y file.txt:

1
2
C:\symlink.txt
C:\symlink.txt

Sin embargo, este no es el caso aquí. Esto se debe al hecho de que el enlace simbólico se creó en Windows con NTFS (Sistema de archivos de nueva tecnología). El enlace simbólico se creó usando el comando mklink en el CMD.

Comprobar si existe

De los ejemplos anteriores, es evidente que el método Files.exists() devolverá true tanto para los archivos como para los directorios existentes. Sin embargo, no funciona mejor cuando se trata de archivos bloqueados.

Por otro lado, el método exists() de la clase File también devolverá true tanto para archivos como para directorios y puede leer el archivo bloqueado que la clase Files no puede.

Conclusión

Verificar la existencia de archivos y directorios es la primera línea de defensa contra la falta de archivos y directorios. Los diferentes enfoques tienen diferentes contratiempos y puede suponer que un método arrojará un resultado preciso, pero no lo hará debido a cómo funciona en segundo plano.

Ser consciente de qué métodos devuelven qué resultados en qué circunstancias le permitirá evitar excepciones desagradables al manejar archivos.

After checking if your file exists or not, you'll likely want to do some Leer y escribir archivos en Java.

Licensed under CC BY-NC-SA 4.0