Introducción a Java NIO - Parte 2 (Final)



Hola y buen día a todos mis lectores :D, hoy, en lugar de “jugar” a la política o a diseñar sistemas, me decidí por terminar este tutorial sobre el API NIO (o NIO.2), aquí les va…


Flujos de carpetas (Directory streams). Los FileVisitors son bastante 
personalizables, pero cuando todo lo que necesitas mirar es cierto archivo en una sola 
carpeta, una solución más simple existe en la forma de los flujos de carpetas. En una
palabra, un flujo es simplemente un objeto iterable que corre sobre un conjunto de 
rutas que concuerdan con cierto filtro. Es además una interface AutoCloseable para 
usar en sentencias try-with-resources, porque los flujos de carpetas necesitan ser
cerrados.


A continuación se muestra cómo podemos ver todas las entradas en la raíz del JAR anterior.
Y a continuación se muestra cómo podemos pasar un filtro glob a una lista sólo los archivos de clase Java.
Búsquedas más elaboradas pueden ser implementadas pasando un objeto DirectoryStream.Filter como un flujo predicado. Por ejemplo, podemos reusar el objeto glob matcher que usamos antes para listar todas las clases Java, como se muestra a continuación:
Como en el caso de los visitantes de archivos, la predicción (predicate) no necesita estar basada en buscar un PathMatcher. Podrías, por ejemplo, mirar el tamaño de archivo o los atributos de archivo para formar consultas como “cualquier archivo ejecutable sobre 1024kilo-octetos de tamaño.”


Copiando un árbol de archivo completo en un archivo zip. Podemos fácilmente combinar un árbol de archivo andante, las operaciones de clase Files, y un sistema de archivo ad hoc para copiar todo el árbol de archivo de carpeta actual en un archivo zip codificado UTF-8, como se muestra a continuación:
Si en lugar de copiar archivos en un archivo zip, tuviéramos un sistema de archivos FTP para copiar archivos a un servidor remoto FTP, el código de arriba no debería cambiar mucho, excepto por la creación del sistema de archivo. El método Files.createDirectories() cubre la creación de todos los directorios que necesiten existir con el fin de llevar a que la carpeta sea creada.

Manipulando metadatos
Una de las características más interesantes del API NIO.2 es la habilidad de manipular 
metadatos a nivel del sistema de archivos. Anteriormente, información como el dueño del 
archivo, grupo y permisos de acceso no estaban disponibles en el estándar Java runtime
sin recurrir a ejecución de procesos externos o integración de código nativo, ambos de los 
cuales agregan so propio conjunto de problemas. Mientras tal información ha dejado de estar
 escondida, el código necesita adaptarse a las capacidades del entorno de ejecución, 
porque los sistemas operativos y los sistemas de archivos varían grandemente.

El paquete java.nio.file.attribute provee soporte para accesar a tales metadatos, en su 
mayoría usando una jerarquía de file attribute views. Cada vista representa un conjunto de 
metadatos que pueden ser manipulados dependiendo de lo que provee el sistema de archivos
subyacente.

La interfaz BasicFileAttributeView define los atributos que son comunes para los 
sistemas de archivos existentes, como el tamaño del archivo, fecha de última 
modificación, y fecha de creación. Instancias de DosFileAttributeView define atributos de 
los sistemas de archivos tipo DOS, como  si un archivo está oculto, un archivo de sistema o 
un archivo. En el mismo espíritu, PosixFileAttributeView define atributos para los 
sistemas POSIX, mientras AclFileAttributeView permite accesar a las listas de control de 
accesos (ACLs) en los sistemas de archivo que los soportan.

El Javadoc para el paquete java.nio.file.attribute a fondo describe estas vistas. Vamos 
a ver algunos patrones de uso común.
Atributos de archivo. Los atributos de archivos más comunes son accesibles 
directamente desde los métodos de clase Files: size(), isDirectory(), isRegularFile()
isSymbolicLink(), isHidden(), getLastModifiedTime() y más.

Para accesar o modificar un solo atributo, puedes usar los métodos getAttribute()
setAttribute(). Ellos toman un solo String que representa el atributo, prefijado con un 
identificador de la vista de atributo de archivo. Cada interface de la vista de atributo de 
archivo define tales Strings y el return type del atributo en el Javadoc correspondiente.

Podemos consultar los permisos POSIX para un archivo como se muestra a continuación:

Lo que resultaría en una salida similar a la siguiente:
Además, podemos accesar a atributos específicos usando el método readAttributes() en cualquier subclase de BasicFileAttributes, como se muestra a continuación:
Vale la pena que Files.readAttributes(Path, BasicFileAttributes, LinkOption[]) realice operaciones masivas de lectura. Esta capacidad es útil al rendimiento cuando múltiples atributos son leídos simultáneamente.

Los permisos de archivo POSIX pueden ser directamente accesados como se muestra a continuación:

Casos más generales pueden ser manejados primero accesando a una vista de atributo de archivo. Por ejemplo, para obtener el dueño de archivo POSIX de un archivo, puedes usar el código a continuación:
 Los permisos de archivo POSIX son comúnmente expresados en la forma de una String como rwxr-xr-x, lo cual significa que el usuario puede leer, escribir y ejecutar, mientras que los miembros del grupo y otros pueden solo leer y ejecutar. Podemos mostrar tales permisos y cambiarlos, como se muestra a continuación:
Lo que produce una salida similar a ésta: 



Old permissions: rw-r--r--
New permissions: rwxr-xr-x


La clase FileStore. Cada ruta tiene un objeto file store asociado que esencialmente 
representa donde es guardado el correspondiente archivo: volumen, partición y demás. La 
clase FileStore es útil para consultar si el archivo almacenado soporta una dada vista 
de atributo de archivo. Es además útil para accesar a las estadísticas de uso de disco.
El código a continuación nos permite realizar unas cuantas consultas que producen 
salida similar a lo siguiente en Mac OS X:

Código:
Salida:
/dev/disk0s2
hfs
169030116 / 244277768
true
true
false





Atentos a los cambios
Algunas aplicaciones necesitan estar atentas a los cambios del sistema de archivos. 
Por ejemplo, un servidor de aplicación quizá esté atento a que los ficheros de aplicación sean
 dejados en cierta carpeta y entonces automáticamente desplegarlos. Similarmente, los 
entornos de desarrollo integrado (IDEs) pueden buscar archivos de proyecto para que 
sean agregados, eliminados y modificados por aplicaciones de terceros. Otro ejemplo 
incluye algunos patrones de integración de aplicaciones donde las aplicaciones intercambian 
datos a través de depósitos de archivo.

Estar atento a los cambios en el sistema de archivo puede ser implementado fácilmente 
mirando periódicamente a las entradas de una carpeta y determinando qué archivos han 
sido agregados, eliminados o cambiados basados en su fecha de última modificación. De 
todas formas, mecanismos más eficientes existen a nivel de sistema operativo, como inotify 
para Linux.

NIO.2 Provee una API útil que toma ventaja de las facilidades del sistema operativo, cuando 
están disponibles claro, y cae de nuevo a votación periódica de otra manera. WatchService provee 
un servicio que puede ser notificado sobre cambios en un dado objeto Path. Puedes 
especificar qué tipos de eventos deberían ser mirados, saber las adiciones, modificaciones, 
eliminaciones o desbordamiento (falla del sistema de notificaciones o reporte de todos los 
eventos). Por ejemplo, el fragmento de código a continuación busca por cambios en /tmp
imprime todos los eventos:

Un WatchService es obtenido del sistema de archivo de la ruta a ser monitorizada. De 
nuevo, este es un objeto AutoCloseable, y es una buena idea usarlo con una 
sentencia try-with-resources para asegurar que eventualmente se cerrará. El servicio 
de vigilancia es entonces registrado a una ruta, y los eventos se vuelven disponibles desde 
una cola.


Un WatchKey es usado en conjunto con registro y es devuelto al momento de registo. Un 
WatchKey es además obtenido cuando buscamos eventos usando ya sea el método de 
servicio de vigilancia poll() o take(). En el ejemplo de código anterior (el de arriba), 
optamos por usar take() porque podemos permitirnos esperar a que un nuevo evento 
esté disponible. Una llave de vigilancia (watch key) mantiene el estado, así que podemos 
consultar para determinar dónde es aún válido y para obtener los últimos eventos de 
vigilancia.

Una vez que una llave ha sido usada, necesita ser reseteada si se va a usar de nuevo. El 
método reset() devuelve un valor Boolean que será false si la llave ya no es válida, por 
ejemplo, cuando una carpeta vigilada desaparece. Puedes además llamar al método cancel() 
para cancelar el registro del servicio de vigilancia.

Finalmente, la llave tiene información sobre el evento. Por ejemplo, podría sostener 
información del tipo de evento (más probable desde StandardWatchEventKinds) y un 
objeto de contexto que es una instancia de Path, el cual corresponde al tipo de eventos 
que el servicio está buscando (ENTRY_CREATE, ENTRY_MODIFY y ENTRY_DELETE).

Conclusión
Este artículo introdujo la nueva API del sistema de archivo liberado en Java SE 7 como parte 
del paquete llamado NIO.2. Estos paquetes hacen fácil tratar con operaciones de archivo ya 
sean comunes o avanzadas, como lo es un eficiente monitor de cambios en una carpeta o 
mover archivos a un archivo comprimido en zip mientras se preservan los metadatos.
 Y último pero no menos importante, se integran bien con las clases existentes java.io
y java.nio, y pueden ser extendidas para tratar uniformemente con nuevos tipos de 
proveedores de sistemas de archivos. Para más ejemplos vea el código de muestra NIO.2 
en la distribución del JDK7 (bajo simple/nio/file).

Y bien, este es el final del tutorial sobre Java NIO (ahora sí voy a disfrutar de mi frappé :P), 
espero les haya sido de utilidad, no olviden suscribirse (e-mail, RSS, Atom), comentar, hacer 
peticiones, plantear sus dudas o críticas constructivas en la parte de abajo, ahhh y votar también, 
saludos :D.

Entradas Relacionadas:


Comentarios

Publicar un comentario