CodeGym /Cursos /JAVA 25 SELF /Clases File, Path y Files: obtención de información sobre...

Clases File, Path y Files: obtención de información sobre archivos

JAVA 25 SELF
Nivel 39 , Lección 1
Disponible

1. Repaso: File vs Path vs Files

El veterano File

Sí… hay bastante código heredado (legacy) en los proyectos Java. Así que volvamos a recordar al veterano de Java, la clase File. Apareció en el lenguaje ya en la primera versión y permite trabajar con archivos y carpetas: saber si un archivo existe, su nombre, tamaño, fecha de modificación; crear y eliminar archivos y carpetas. Como ya sabemos, está lleno de inconvenientes: algunos métodos no son intuitivos, no todas las operaciones están soportadas de forma multiplataforma y algunos métodos no lanzan excepciones, sino que simplemente devuelven false (lo que no siempre es cómodo para depurar).

import java.io.File;

File file = new File("example.txt");
System.out.println("¿Existe el archivo? " + file.exists());
System.out.println("¿Es un archivo? " + file.isFile());
System.out.println("¿Es una carpeta? " + file.isDirectory());

Path y Files: visión moderna (Java 7+)

Con la llegada de Java 7 apareció el paquete java.nio.file, que ofrece herramientas más potentes y flexibles. Dos protagonistas clave:

  • Path — una interfaz que describe la ruta a un archivo o carpeta. Se podría decir que es «una cadena con inteligencia»: sabe descomponer, unir, analizar y comparar rutas.
  • Files — una clase utilitaria con un montón de métodos estáticos para trabajar con archivos y directorios: crear, eliminar, copiar, leer, escribir y obtener información.
import java.nio.file.Path;
import java.nio.file.Paths;

Path path = Paths.get("example.txt");
System.out.println("Ruta: " + path);

Dato curioso: la clase Path no es solo una cadena. Conoce los separadores de directorios, sabe manejar rutas relativas y absolutas y funciona igual de bien en Windows y Linux.

Tabla comparativa de File y Path/Files

Criterio File (API antiguo) Path + Files (API moderno)
Sintaxis Estilo POO Combinación de Path + métodos estáticos de Files
Compatibilidad multiplataforma Parcial Excelente; tiene en cuenta el sistema operativo
Excepciones No siempre Casi siempre
Nuevas funcionalidades No Sí (atributos, permisos, enlaces, etc.)
Recomendado Más bien no

2. Obtención de información sobre un archivo/directorio

Veamos cómo averiguar lo más importante sobre un archivo o una carpeta: si el objeto existe, su tipo (archivo o directorio), tamaño, nombre, ruta y directorio padre.

Comprobación de existencia

Con File

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

Con Path y Files

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

Path path = Paths.get("example.txt");
if (Files.exists(path)) {
    System.out.println("¡El archivo existe!");
} else {
    System.out.println("Archivo no encontrado.");
}

Consejo: Para proyectos nuevos, utiliza siempre Path y Files. Es más seguro, más cómodo y multiplataforma.

Comprobación del tipo: archivo o directorio

File

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

Path + Files

if (Files.isRegularFile(path)) {
    System.out.println("Es un archivo.");
} else if (Files.isDirectory(path)) {
    System.out.println("Es una carpeta.");
}

Obtención del tamaño de un archivo

File

long size = file.length();
System.out.println("Tamaño del archivo: " + size + " bytes");

Path + Files

try {
    long size = Files.size(path);
    System.out.println("Tamaño del archivo: " + size + " bytes");
} catch (IOException e) {
    System.out.println("Error al obtener el tamaño del archivo: " + e.getMessage());
}

Atención: Para una carpeta, el método length() siempre devolverá 0, y Files.size(path) lanzará IOException. El tamaño de una carpeta es la suma de los tamaños de todos los archivos que contiene (más detalles en las siguientes lecciones).

Obtención de la ruta absoluta y relativa

File

System.out.println("Ruta relativa: " + file.getPath());
System.out.println("Ruta absoluta: " + file.getAbsolutePath());

Path

System.out.println("Ruta relativa: " + path);
System.out.println("Ruta absoluta: " + path.toAbsolutePath());

Obtención del nombre de archivo y el directorio padre

File

System.out.println("Nombre del archivo: " + file.getName());
System.out.println("Directorio padre: " + file.getParent());

Path

System.out.println("Nombre del archivo: " + path.getFileName());
System.out.println("Directorio padre: " + path.getParent());

Truco: Path puede trabajar no solo con archivos, sino también con carpetas; con rutas relativas y absolutas, y además descompone una ruta en partes con facilidad.

3. Obtención de atributos de archivo

A veces queremos saber no solo el tamaño y el nombre de un archivo, sino también algo más interesante: fecha de creación, fecha de la última modificación y permisos de acceso.

Fecha de creación y última modificación

File (limitado)

long lastModified = file.lastModified();
System.out.println("Fecha de la última modificación: " + new java.util.Date(lastModified));

Inconveniente: ¡No es posible obtener la fecha de creación del archivo a través de File!

Path + Files

import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;

try {
    BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
    FileTime creationTime = attrs.creationTime();
    FileTime lastModifiedTime = attrs.lastModifiedTime();

    System.out.println("Fecha de creación: " + creationTime);
    System.out.println("Fecha de la última modificación: " + lastModifiedTime);
} catch (IOException e) {
    System.out.println("Error al obtener atributos: " + e.getMessage());
}

Comprobación de permisos de acceso

File

System.out.println("¿Se puede leer? " + file.canRead());
System.out.println("¿Se puede escribir? " + file.canWrite());
System.out.println("¿Se puede ejecutar? " + file.canExecute());

Path + Files

System.out.println("¿Se puede leer? " + Files.isReadable(path));
System.out.println("¿Se puede escribir? " + Files.isWritable(path));
System.out.println("¿Se puede ejecutar? " + Files.isExecutable(path));

Dato curioso: En Windows los permisos de acceso son limitados, mientras que en sistemas Unix se pueden obtener y cambiar muchos más (por ejemplo, mediante atributos POSIX).

4. Errores comunes al obtener información sobre archivos

Error n.º 1: Usar File cuando se necesita Path.
Muchos principiantes siguen utilizando File porque les resulta más sencillo o «porque así es en todo Internet». Pero con Path y Files se puede hacer lo mismo, de forma más fiable y moderna.

Error n.º 2: Comprobar el tipo de objeto solo con File.
Si solo utilizas file.isFile() y file.isDirectory(), puedes pasar por alto archivos «especiales» (enlaces simbólicos, dispositivos). En el API moderno existen Files.isRegularFile(path), Files.isDirectory(path) y otras comprobaciones.

Error n.º 3: Ignorar las excepciones.
Los métodos Files.size(path) y Files.readAttributes(...) lanzan IOException. Si no se gestionan las excepciones, el programa se caerá ante el primer error de acceso o si el archivo desaparece durante la ejecución.

Error n.º 4: Esperar que el tamaño de una carpeta se pueda obtener directamente.
El método Files.size(path), para una carpeta, lanzará una excepción. Para conocer el tamaño de una carpeta, hay que sumar de forma recursiva los tamaños de todos los archivos que contiene.

Error n.º 5: Comprobación insuficiente de los permisos de acceso.
Incluso si el archivo existe, es posible que no tengas permisos para leerlo o escribirlo. Comprueba siempre los permisos antes de realizar operaciones: Files.isReadable(path), Files.isWritable(path), Files.isExecutable(path).

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