Menú de navegaciónMenú
Categorías

La mejor forma de Aprender Programación online y en español www.campusmvp.es

?id=a3e627ca-e1d1-4af9-8a3e-7fe12ceb7fb2

Java: cómo listar, filtrar y obtener información de carpetas y archivos

Una tarea común y básica que necesitamos hacer en cualquier programa es acceder a la información de los archivos y carpetas del sistema de archivos local. Desde algo tan básico como ver el nombre y el tamaño de un archivo hasta listar los contenidos de cualquier carpeta.

En Java esto es muy fácil de conseguir gracias a la clase java.io.File. Esta clase nos permite obtener información sobre cualquier elemento del sistema de archivos.

Para utilizarla solo tenemos que importarla en la cabecera de nuestro programa:

import java.io.File;

Y podremos utilizarla en nuestra aplicación.

Para obtener información sobre un archivo o carpeta basta con usar su constructor pasándole la ruta de éste. Así:

String sCarpAct = System.getProperty("user.dir");
File carpeta = new File(sCarpAct);

En la primera línea obtenemos la carpeta actual desde la que se está ejecutando el código, y utilizamos la clase File para obtener información sobre la misma. A este constructor le podemos pasar una ruta absoluta o relativa en el sistema de archivos.

La clase File sirve para representar a un archivo o carpeta y ofrece propiedades y métodos que nos permiten acceder a sus datos y realizar operaciones sobre ellos, como renombrar, eliminar, crear carpetas, listar sus contenidos, etc... Lo que podamos hacer con ella dependerá de los permisos que tengamos sobre el archivo o carpeta en cuestión. 

Algunos de los métodos de File mostrados por la ayuda contextual de un editor

Algunos de estos métodos son:

  • canExecute(): devuelve un true o false en función de si el archivo es ejecutable o no.
  • canRead(): si tienes acceso de lectura o no
  • canWrite(): si puedes escribir en él o no
  • createNewFile(): crea un nuevo archivo vacío con el nombre que se le indique.
  • delete(): borra el archivo o directorio
  • exists(): determina si el archivo representado por File en la ruta que le hayamos pasado existe o no.
  • getName(): el nombre del archivo o carpeta
  • getParent(): devuelve una cadena con la ruta de la carpeta "madre" del archivo o carpeta actuales.
  • isDirectory(): indica si el objeto actual representa a una carpeta o no
  • isFile():  indica si el objeto actual representa a un archivo
  • isHidden(): si es un elemento oculto en el sistema de archivos
  • length(): el tamaño del archivo en bytes. Si no existe o no tienes permiso devuelve un 0. En el caso de carpetas en Linux/Mac con sistema de archivos ext3/ext4 siempre devuelve 4096 ya que este es el tamaño de un bloque en Linux y es el mínimo que puede ocupar cualquier enlace en disco, como una carpeta (4KB).
  • list(): los nombres de los archivos y carpetas hijos de una carpeta.
  • listFiles(): como el anterior pero devolviendo objetos File para cada archivo o carpeta.
  • mkdir(): crea una carpeta
  • renameTo(): renombra el archivo o carpeta

Con todo esto se pueden hacer muchas cosas. Consúltalos todos en la documentación con el enlace anterior.

Vamos a ver un ejemplo de cómo listar todos los archivos de una carpeta usando varios de estos métodos:

File carpeta = new File(sCarpAct);
String[] listado = carpeta.list();
if (listado == null || listado.length == 0) {
System.out.println("No hay elementos dentro de la carpeta actual");
return;
}
else {
for (int i=0; i< listado.length; i++) {
System.out.println(listado[i]);
}
}

Lo que se hace en este fragmento es:

  1. Se crea un nuevo objeto File para representar la carpeta que nos interesa.
  2. Con el método list() obtenemos los nombres de todos sus hijos
  3. Si no devuelve nada o la longitud es 0 mostramos un mensaje de que no hay elementos en la carpeta actual (también podríamos haber comprobado si es una carpeta o no con isDirectory())
  4. En la otra rama del condicional recorremos en un bucle sencillo todos los nombres de elementos hijo mostrando sus nombres cada uno en una línea en la consola.

Veríamos algo como esto:

Está bien para replicar el comando ls (Linux, Mac) o dir (Windows) básico de la línea de comandos, pero si queremos más información no nos va a servir de mucho.

Podemos mejorarlo utilizando el método listFiles() que nos devuelve objetos File y por lo tanto podemos mostrar más información de cada uno sin tener que crearlos explícitamente, así:

File[] archivos = carpeta.listFiles();
if (archivos == null || archivos.length == 0) {
System.out.println("No hay elementos dentro de la carpeta actual");
return;
}
else {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
for (int i=0; i< archivos.length; i++) {
File archivo = archivos[i];
System.out.println(String.format("%s (%s) - %d - %s",
archivo.getName(),
archivo.isDirectory() ? "Carpeta" : "Archivo",
archivo.length(),
sdf.format(archivo.lastModified())
));
}
}

En este caso el código es parecido, pero podemos utilizar los métodos que hemos visto para mostrar más información sobre cada elemento. En este caso mostramos su nombre, si es un directorio o un archivo, su tamaño y la fecha de última modificación. Para mostrar la fecha en un formato adecuado utilizo la clase SimpleDateFormater del paquete java.text.SimpleDateFormat.

Bien. Pero, ¿qué pasa si no queremos mostrar todos los archivos, sino sólo los que cumplan con ciertas condiciones?

Para eso podemos utilizar un filtro. Los filtros son clases que implementan la interfaz FilenameFilter (si solo queremos filtrar por el nombre) o FileFilter (si queremos usar objetos File para el filtrado). Esta interfaz lo único que define es un método accept() que, en su sobrecarga más simple, toma como parámetro el archivo a filtrar y debe devolver true o false en función de si el archivo pasa el filtro o no.

Por ejemplo, vamos a filtrar los elementos de nuestra carpeta para que devuelve únicamente archivos, pero no carpetas. Es una condición sencilla, pero lógicamente podríamos aplicar cualquier regla compleja que nos interesase en función de las propiedades disponibles de cada elemento (su nombre, tamaño, permisos... o una combinación de varios de ellos).

Veamos cómo hacerlo.

En primer lugar vamos a definir el filtro:

FileFilter filtro = new FileFilter() {
@Override
public boolean accept(File arch) {
return arch.isFile();
}
};

En este caso, por brevedad, he usado un literal con el constructor para crear el objeto e implementar el método accept(), pero podría haber creado la clase de la manera más convencional usando implements para implementar la interfaz, etc.. La forma es lo de menos. Lo único que hace es llamar al método isFIle() de cada archivo o carpeta para devolver true solo en caso de que sean archivos. De este modo solamente se obtendrán archivos y ninguna carpeta tras realizar el filtrado.

Ahora utilizarlo es tan sencillo como pasar el nuevo objeto de filtro al método listFiles(), así:

archivos = carpeta.listFiles(filtro);

if (archivos == null || archivos.length == 0) {
System.out.println("No hay elementos dentro de la carpeta actual");
return;
}
else {
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
for (int i=0; i< archivos.length; i++) {
File archivo = archivos[i];
System.out.println(String.format("%s (%s) - %d - %s",
archivo.getName(),
archivo.isDirectory() ? "Carpeta" : "Archivo",
archivo.length(),
sdf.format(archivo.lastModified())
));
}
}

Tan solo cambia la primera línea. El resto es como en el ejemplo anterior, solo que en este caso veremos en la consola únicamente los archivos y no los directorios gracias al filtro que hemos aplicado.

Como ves el uso de esta clase es extremadamente sencillo.

Te dejo todo el código de ejemplo en este repl.it, embebido a continuación. Pulsa el triángulo de la parte de arriba para ejecutarlo directamente en el navegador y ver sus resultados:

Nota: si te preguntas cómo hago lo de mostrar colores en la consola, lee este otro artículo.

¡Espero que te resulte útil!

José Manuel Alarcón Fundador de campusMVP, es ingeniero industrial y especialista en consultoría de empresa. Ha escrito diversos libros, habiendo publicado hasta la fecha cientos de artículos sobre informática e ingeniería en publicaciones especializadas. Microsoft lo ha reconocido como MVP (Most Valuable Professional) en desarrollo web desde el año 2004 hasta la actualidad. Puedes seguirlo en Twitter en @jm_alarcon o leer sus blog técnico o personal. Ver todos los posts de José Manuel Alarcón
Archivado en: Lenguajes y plataformas

¿Te ha gustado este post?
Pues espera a ver nuestro boletín mensual...

Suscríbete a la newsletter

La mejor formación online para desarrolladores como tú

Agregar comentario

Los datos anteriores se utilizarán exclusivamente para permitirte hacer el comentario y, si lo seleccionas, notificarte de nuevos comentarios en este artículo, pero no se procesarán ni se utilizarán para ningún otro propósito. Lee nuestra política de privacidad.