FileUtils de Apache Commons IO en Java

Commons IO nació cuando el JDK no tenía nada parecido. Buena parte de lo que hacía está hoy en java.nio.file, pero quedan unas cuantas cosas que siguen mereciendo la dependencia, y conviene saber cuáles son.

La dependencia

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.22.0</version>
</dependency>

Lo que de verdad sigue valiendo la pena

FileUtils.copyDirectory(base, new File("ci-copia"));
FileUtils.deleteDirectory(base);
salidacopiada entera, archivos: 3
borradas   : true

Copiar y borrar una carpeta con todo lo que hay dentro. En el JDK pelado esto es un Files.walk con relativize, o un walk ordenado al revés, y en los dos casos hay que lidiar con la IOException dentro de la lambda. Aquí es una línea. Es la razón número uno para añadir esta biblioteca.

System.out.println(FileUtils.sizeOfDirectory(base) + " bytes");
System.out.println(FileUtils.byteCountToDisplaySize(1536L * 1024 * 1024));
salida27 bytes
1 GB

sizeOfDirectory suma el tamaño de todo el árbol. byteCountToDisplaySize escribe el tamaño para una persona, aunque conviene saber que trunca en vez de redondear: 1,5 GB sale como «1 GB».

Buscar archivos por extensión

Collection<File> txt = FileUtils.listFiles(base, new String[]{"txt"}, true);
System.out.println(txt.stream().map(File::getName).sorted().toList());
salida[a.txt, b.txt]

El tercer argumento es si entra en las subcarpetas. Con los filtros de org.apache.commons.io.filefilter se pueden combinar condiciones por edad, tamaño o nombre sin escribir predicados.

FilenameUtils: la parte que el JDK sigue sin tener

System.out.println(FilenameUtils.getExtension("/ruta/informe.tar.gz"));
System.out.println(FilenameUtils.getBaseName("/ruta/informe.tar.gz"));
System.out.println(FilenameUtils.normalize("/a/b/../c/./d.txt"));
System.out.println(FilenameUtils.wildcardMatch("informe-2026.pdf", "informe-*.pdf"));
salidagz
informe.tar
/a/c/d.txt
true

Sacar la extensión de un nombre parece trivial hasta que aparecen los archivos sin extensión, los que empiezan por punto y los .tar.gz. FilenameUtils trabaja sobre cadenas, sin tocar el disco, y entiende tanto las barras de Unix como las de Windows.

Y lo que ya no hace falta

Commons IOEn el JDK desde
FileUtils.readFileToStringFiles.readString (Java 11)
FileUtils.writeStringToFileFiles.writeString (Java 11)
FileUtils.readLinesFiles.readAllLines (Java 7)
FileUtils.copyFileFiles.copy (Java 7)
FileUtils.forceMkdirFiles.createDirectories (Java 7)
IOUtils.toString(flujo)flujo.readAllBytes() (Java 9)
IOUtils.copyflujo.transferTo(salida) (Java 9)
Si el proyecto ya tiene la dependencia, úsala con tranquilidad. Pero no la añadas solo para leer un archivo: eso son tres jars más en el despliegue y una cosa más que actualizar cuando salga un aviso de seguridad, a cambio de algo que el JDK hace igual de bien desde hace años. Las que sí justifican la dependencia son las de arriba: copyDirectory, deleteDirectory, sizeOfDirectory y FilenameUtils.

Más información en inglés: Apache Commons IO FileUtils in Java.

Todo el código se compiló y se ejecutó con Java 25 LTS en un contenedor limpio antes de publicar esta página; las salidas están copiadas de esa ejecución.