Blog

Java NIO

Java NIO
Publicado por: Gerardo Arroyo Arce

En este artículo explicaremos como recorrer una estructura de directorios por medio de NIO y Streams.

Java NIO

En Java 7 se introdujo el NIO.2 (nonblocking input/output) y ahi se agregan nuevas clases para la manipulación de archivos y directorios. Además se mejoraron para permitir el uso de Streams; en este aspecto sólo debemos recordarles que -por ejemplo- la interface jav.nio.file.DirectoryStream no tiene nada que ver con los streams funcionales. El nombre tiende a la confusión; y esperamos que eventualmente Java reorganice el nombre de estas clases.

Utilización

Supongamos que como parte de un proyecto, se les encomienda la tarea de recorrer una estructura de directorios; como ilustración: directorios con archivos que deben procesarse, o XML para ser enviados a una cola, etc.

En Java 8 y subsiguientes; eso se puede lograr por medio del método Files.walk. Este método tiene como firma lo siguiente:

{% highlight java %}
public static Stream<Path> walk(Path start, FileVisitOption… options) throws IOException
{% endhighlight %}

Los argumentos corresponden al Path de inicio y una lista de argumentos del tipo FileVisitOption. El tipo que retorna es un Stream lazy de instancias de Path obtenidas al recorrer el sistema de archivos iniciando en el punto de origen indicado.

Por ejemplo, el código que mostramos seguidamente recorre todo los archivos a partir de un punto de inicio e imprime su ruta y nombre completo.

{% highlight java %}
try (Stream<Path> paths = Files.walk(Paths.get(“/opt/demos”))) {
paths.forEach(System.out::println);
}
{% endhighlight %}

Observen que no enviamos ningún argumento adicional al método walk. El resultado tiene la garantía que regresa al menos un elemento; que sería el argumento o path de inicio. Conforme cada path es localizado, el sistema determina si es un directorio; y si lo es, lo recorre antes de continuar. Es decir, hace un recorrido por profundidad primero.

En ocasiones, no es deseable o necesario recorrer toda la estructura de directorios; pues nos interesa sólo un nivel de profundidad. Para ellos podemos hacer uso del método walk de la siguiente manera:

{% highlight java %}
try (Stream<Path> paths = Files.walk(Paths.get(“/opt/demos”), 1)) {
paths.forEach(System.out::println);
}
{% endhighlight %}

En ese código, únicamente bajamos un nivel en la estructura de directorios. Si colocamos el valor 0; es equivalente a decir que nos quedamos al nivel del path de inicio.

Por último, puede ser necesario que te interesen solo archivos con ciertos atributos. Para ello se tiene el método find que permite lograr lo anterior; como mostramos de seguido.

{% highlight java %}
try (Stream<Path> paths = Files.find(Paths.get(“/opt/demos”),
Integer.MAX_VALUE,
(path, attributes)
-> !attributes.isDirectory() && path.toString().contains(“java”))) {
paths.forEach(System.out::println);
}
{% endhighlight %}

En este ejemplo; indicamos el path de inicio; el Integer.MAX_VALUE es el nivel de profundidad que equivale a recorrer todo y luego un BiPredicate para determinar si un Path determinado debe ser retornado o no. En este caso, se omiten directorios y deben ser archivos que contengan la palabra java en alguna parte. Es importante tomar en cuenta que el BiPredicate debe retornar un valor booleano.

Conclusión

Esperamos que con este artículo les invite a investigar sobre Java NIO2 en sus desarrollos.

Java NIO

Gerardo Arroyo Arce

CEO & Co-Founder

  • ​AWS Community Builder & Ambassador
  • ​AWS Solution Architect - Professional
  • AWS Certified Database – Specialty
  • AWS Certified Security – Specialty
  • AWS Solution Architect - Associate
  • AWS Certified Developer Associate
  • AWS Certified SysOps Administrator Associate
  • Ingeniero en Software. ITCR.
  • Master en Computación en Informática. UCR.