CodeGym /Cursos /JAVA 25 SELF /Comprobación de la existencia de archivos y directorios

Comprobación de la existencia de archivos y directorios

JAVA 25 SELF
Nivel 38 , Lección 1
Disponible

1. Métodos para comprobar la existencia de archivos y directorios

Trabajar con archivos a veces se parece a caminar por un campo de minas: nunca sabes qué te espera tras el siguiente byte. La buena noticia: Java nos da un «detector de metales» — métodos para comprobar la existencia de archivos y carpetas.

Clase File: comprobación con exists(), isFile(), isDirectory()

La forma clásica es usar la clase java.io.File:

File file = new File("example.txt");
if (file.exists()) {
    System.out.println("¡El archivo existe!");
} else {
    System.out.println("Archivo no encontrado.");
}

El método exists() devuelve true si existe un archivo o carpeta con ese nombre. ¡Pero eso no es todo! A veces necesitas saber qué es exactamente lo que existe: un archivo o un directorio.

if (file.isFile()) {
    System.out.println("Es un archivo.");
} else if (file.isDirectory()) {
    System.out.println("Es una carpeta.");
} else {
    System.out.println("No se encontró nada.");
}

Clases Path y Files: enfoque moderno

En aplicaciones modernas es mejor utilizar la API más nueva y potente java.nio.file. Aquí se utiliza el método estático Files.exists() para comprobar la existencia:

import java.nio.file.*;

Path path = Paths.get("example.txt");
if (Files.exists(path)) {
    System.out.println("¡Archivo encontrado con NIO!");
}

Para comprobar el tipo del objeto, utiliza:

if (Files.isRegularFile(path)) {
    System.out.println("¡Es un archivo regular!");
}
if (Files.isDirectory(path)) {
    System.out.println("¡Es un directorio!");
}

Consejo: para proyectos nuevos, es mejor usar desde el principio NIO (Path, Files), porque esta API es más moderna, admite más funciones y se lleva bien con try-with-resources.

Tabla: comparación de enfoques

Método Comprobación de existencia Comprobación de tipo (archivo/carpeta) Modernidad
File.exists()
Sí (isFile(), isDirectory()) Antiguo
Files.exists(Path)
Sí (isRegularFile(), isDirectory()) Recomendado

2. Problema TOCTOU: por qué la comprobación no es una panacea

¿En qué consiste el problema?

Supongamos que has comprobado: «¡El archivo existe!» — e inmediatamente decides leerlo. Pero entre esas dos acciones puede pasar una eternidad en términos de procesador. En ese tiempo, el archivo puede ser eliminado, movido, reemplazado por otro proceso o sus permisos pueden cambiar.

Es como mirar dentro del frigorífico, notar que hay una tarta, cerrar la puerta y, al abrirla de nuevo, descubrir que la tarta ya se la han comido. En programación también hay esos «convivientes»: otros procesos, usuarios, antivirus y el propio sistema de archivos.

¿Por qué es importante?

Como resultado, incluso si has comprobado que el archivo existe, al intentar abrirlo puede producirse una excepción — por ejemplo, FileNotFoundException o AccessDeniedException.

Así que la comprobación no es una garantía, sino solo un seguro adicional. ¡Está siempre preparado para las excepciones y manéjalas!

3. Práctica: comprobar la existencia de un archivo antes de leerlo

Vamos a añadir una función que muestre el contenido del archivo si existe e informe al usuario si el archivo no está. Mostraremos dos variantes: con la API antigua y con la nueva.

Opción 1: con File

import java.io.*;

public class FileExistenceCheck {
    public static void main(String[] args) {
        File file = new File("notes.txt");
        if (file.exists() && file.isFile()) {
            try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                System.out.println("Error al leer el archivo: " + e.getMessage());
            }
        } else {
            System.out.println("No se encontró el archivo 'notes.txt'.");
        }
    }
}

Opción 2: con Path y Files

import java.nio.file.*;
import java.io.IOException;

public class PathExistenceCheck {
    public static void main(String[] args) {
        Path path = Paths.get("notes.txt");
        if (Files.exists(path) && Files.isRegularFile(path)) {
            try {
                Files.lines(path).forEach(System.out::println);
            } catch (IOException e) {
                System.out.println("Error al leer el archivo: " + e.getMessage());
            }
        } else {
            System.out.println("No se encontró el archivo 'notes.txt'.");
        }
    }
}

¡Incluso después de comprobar — seguimos capturando excepciones!

En ambos ejemplos, a pesar de la comprobación previa, seguimos usando bloques trycatch, porque el archivo puede desaparecer o dejar de estar accesible en cualquier momento. ¡Es la regla de oro al trabajar con archivos!

4. Comprobación de la existencia de un directorio

De forma análoga, puedes comprobar la existencia de una carpeta y, si no existe, crearla:

import java.nio.file.*;

public class DirectoryCheck {
    public static void main(String[] args) {
        Path dir = Paths.get("data");
        if (Files.exists(dir) && Files.isDirectory(dir)) {
            System.out.println("Se encontró la carpeta 'data'.");
        } else {
            System.out.println("No se encontró la carpeta 'data'. Creándola...");
            try {
                Files.createDirectory(dir);
                System.out.println("¡Carpeta creada!");
            } catch (IOException e) {
                System.out.println("Error al crear la carpeta: " + e.getMessage());
            }
        }
    }
}

Por cierto:
El método Files.createDirectory() lanza una excepción si la carpeta ya existe. Si quieres crear una cadena de carpetas (por ejemplo, "data/2025/09"), utiliza Files.createDirectories(), que no se queja si alguna de las carpetas ya existe.

5. Particularidades y matices: rutas relativas y absolutas

Rutas relativas

Cuando escribes "notes.txt", el programa busca el archivo en el «directorio de trabajo actual». Dónde está depende de cómo y desde dónde ejecutes la aplicación (IDE, terminal, doble clic en el JAR, etc.).

Rutas absolutas

Si necesitas estar seguro de dónde buscar, es mejor usar rutas absolutas o construirlas dinámicamente:

String userHome = System.getProperty("user.home");
Path filePath = Paths.get(userHome, "myapp", "notes.txt");

Comprobación del tipo del objeto

A veces, un «archivo» puede resultar ser un directorio inesperadamente. Por eso, comprueba no solo la existencia, sino también el tipo:

if (Files.isRegularFile(path)) {
    // ¡Es un archivo!
}
if (Files.isDirectory(path)) {
    // ¡Es una carpeta!
}

6. Demostración práctica del problema TOCTOU

Vamos a simular una situación en la que el archivo desaparece tras la comprobación pero antes de abrirlo. Ejecuta el código y elimina el archivo manualmente entre la comprobación y la lectura:

import java.io.*;
import java.nio.file.*;

public class TOCTOUExample {
    public static void main(String[] args) {
        Path path = Paths.get("notes.txt");
        if (Files.exists(path)) {
            System.out.println("Archivo encontrado, vamos a leerlo ahora...");
            // En este punto, abre el explorador y elimina el archivo "notes.txt" manualmente!
            try {
                Files.lines(path).forEach(System.out::println);
            } catch (IOException e) {
                System.out.println("¡Ups! El archivo desapareció: " + e.getMessage());
            }
        } else {
            System.out.println("Archivo no encontrado.");
        }
    }
}

Resultado:
Si te da tiempo a eliminar el archivo entre la comprobación y la lectura, obtendrás una excepción. Esto demuestra de forma clara que ni siquiera una comprobación cuidadosa te salva de cambios imprevistos.

7. Errores típicos al comprobar la existencia de archivos y carpetas

Error n.º 1: Confiar solo en la comprobación, sin usar try-catch. Como «el archivo existe», se puede leer sin problema — piensan los principiantes. Pero el archivo puede desaparecer o volverse inaccesible y el programa «se caerá».

Error n.º 2: Comprobar solo la existencia sin verificar el tipo. Si solo compruebas exists() y no precisas si es archivo o carpeta, puedes intentar abrir una carpeta como si fuera un archivo y obtener un error.

Error n.º 3: Usar rutas relativas sin entender el directorio de trabajo. El programa busca el archivo «en otro sitio», y el usuario no entiende por qué nada funciona.

Error n.º 4: No tener en cuenta los permisos de acceso. El archivo o la carpeta pueden existir, pero no hay permisos de lectura/escritura. Estos errores solo se manifiestan al intentar abrir el archivo — usa siempre trycatch.

Error n.º 5: Ignorar la sensibilidad a mayúsculas/minúsculas del nombre de archivo en distintos SO. En Windows los nombres de archivo no distinguen mayúsculas/minúsculas, y en Linux sí. El programa puede no encontrar "Notes.txt" si busca "notes.txt".

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION