Nio2, permite un enfoque basado en buffer y canales. Es un nuevo componente aparecido en Java 7. Es un formato asíncrono.
Los buffer son objetos que contienen datos y los canales son los dispositivos propiamente dichos como un archivo o socket. Para usar este sistema, normalmente se obtiene un buffer de datos para guardar los datos y generar la entrada y salida y un canaEditarl para enviarlos.
El paquete java.nio.file y el paquete java.nio.file.attribute proporcionan soporte de entrada y salida para el acceso por defecto del sistema. Esto, no sustituye al paquete java.io sino que da funcionalidad añadida. Es bastante intuitivo y de fácil uso.
Java NIO proporciona funcionalidad para:
- El acceso a estructuras de directorio a través de la clase Path.
- Métodos para manipular Ficheros como, copiar, borrar o mover , además de devolver propiedades de los ficheros a través de la clase Files.
- Podemos obtener información sobre el sistema de ficheros a través de la clase FileSystem.
Un sistema de ficheros organizado en uno o más discos duros se organizan en estructuras jeráquicas. El nivel más alto son los nodos que contienen subniveles de directorios o ficheros.
Path
Un fichero es identificado por un path en la estructura de ficheros. Las distintas rutas para acceder a estos ficheros pueden ser relativas o absolutas.
Rutas Relativas
A partir del directorio actual se realizan las búsquedas de directorios.No se incluye el directorio raíz. Por ejemplo, si estamos en la ruta C:/Raiz/bin y queremos volver al directorio raíz podemos utilizar caracteres como «..», los caracteres tradicionales de búsquedas de directorios.
Rutas Absolutas
En la búsqueda de directorios , a partir de de rutas absolutas, se incluye toda la ruta donde se encuentra el fichero correspondiente. C:/raiz/…
Clase Path
Introducida en el paquete JavaSE7, se encuentra en el paquete java.nio.file. Esta clase es la representación de los path o rutas en el sistema de ficheros.El objeto Path contiene métodos para localizar, examinar y manipular ficheros.
El Path en Solaris, se especifica a través del carácter «/raiz/bin» , mientras que en Windows , la búsqueda se hace con «raiz\bin».
Creación de un Path
Un Path, contiene información para especificar la localización de un fichero o directorio. La estructura de directorios debe de ser incluida para poder hacer la creación. La clase Path , proporciona los siguientes métodos:
Métodos |
Definición |
ToString() |
Retorna la ruta del Path |
getFileName() | Retorna el nombre de la última secuencia de elementos |
getName(0) |
Retorna la ruta de elementos correspondiente al índice específicada |
getNameCount | Retorna el número de elementos del Path |
subPath(0,2) | Retorna la secuencia del path , no incluye el elemento root |
getParent | Retorna el directorio padre |
getRoot | Retorna el elemento root |
Un ejemplo sería el siguiente suponiendo como Path c:/temp/Ejemplo en Windows.
public class Ejer_Pathpublic static void main(String[] args) {
Accecedemos a un Path
Path p1 = Paths.get("c:\\temp\\ejemplo");
System.out.println(p1.toString());
System.out.println(p1.getFileName());
System.out.format("getName(0): %s%n", p1.getName(0));
System.out.format("getNameCount: %d%n", p1.getNameCount());
System.out.format("subpath(0,2): %s%n", p1.subpath(0,2));
System.out.format("getParent: %s%n", p1.getParent());
System.out.format("getRoot: %s%n", p1.getRoot());
}
}
Convertir un Path
Se puede usar un método para convertir un string en un objeto que pueda ser abierto por el navegador. El método toUri, proporciona esta funcionalidad.
System.out.format("%s%n", p1.toUri());
La salida por pantalla sería la siguiente:
file:///c:/temp/ejemplo
El método toRealPath retorna el path real de un fichero existente. Este método ejecuta operaciones como:
- Si el path es relativo , devuelve el path absoluto
- Si el Path contiene elementos redundantes, retorna el path con esos elementos eliminados.
Este método lanza una excepción, un ejemplo sería como los siguiente:
try { Path p2 = p1.toRealPath(); System.out.println("RealPath: "+p2); } catch (NoSuchFileException x) { System.err.format("%s: no encontrado" + " fichero o directorio", p1); // Logic for case when file doesn't exist. ... } catch (IOException x) { System.err.format("%s%n", x); // Logic for other sort of file error. ... }
La visualización del ejemplo sería:
RealPath: C:\TEMP\ejemplo
Enlazar dos Path
Se pueden combinar dos Path, usando el método resolve(). Se pueden pasar rutas parciales, no incluidas en la ruta actual y añadirlas al Path. Estando en la ruta c:\temp\ejemplo incluimos la ruta añadida.
System.out.println( p1.resolve("añadida"));
Comparar dos Path
La clase Path soporta el método equals, con lo que es posible comparar dos Path. No obstante esta clase proporciona los métodos startsWith y endWith para comprobar el principio y fin de una cadena.
Un ejemplo de este método sería el siguiente:
System.out.println("Valor del Path p2: "+p2);
if(p2.startsWith(Paths.get("temp"))||p2.endsWith(Paths.get("añadida"))){
System.out.println("encontraste la ruta");
}
El resultado sería:
Valor del Path p2: c:\temp\ejemplo\añadida
encontraste la ruta
Borrar un fichero o Directorio
Se puede borrar un fichero, directorio o link. La clase File del método delete(path) permite borrar un fichero o directorio de la cadena especificada.
Un ejemplo sería el siguiente:
try {
Files.delete(p2);
System.out.println("ruta borrada");
} catch (NoSuchFileException x) {
Otra opción, es el método deleteIfExists(Path) que borra un fichero, pero si el fichero no existe lanza una excepción.
Metada y Propiedades de Ficheros
Podemos saber los permisos, el directorio, la fecha de creación y el propietario a través de distintos métodos.
Métodos |
Definición |
Size(path) |
Retorna el tamaño en bytes |
isDirectory(path,linkOption) |
Retorna true si el fichero especificado en el Path , se encuentra |
isHidden(Path) | Retrona true si el fichero está oculto para el sistema |
getLastModifiedTime(Path, LinkOption…) | Retorna o modifica la fecha de la última modificación del fichero. |
subPath(0,2) | Retorna la secuencia del path , no incluye el elemento root |
getOwner(Path,LinkOption…) setOwner(Path, UserPrincipal) |
Retorna o modifica el propietario |
getPosixFilePermissions(Path, LinkOption…) setPosixFilePermissions(Path, Set<PosixFilePermission>) |
Retorna o modifica los permisos de un fichero en caracteres Posix. |
Atributos básicos de un fichero
Para poder ver los atributos de un fichero , es posible usar la clase Files.readAttributes, que devuelve una colección de tipo BasicFileAttribute que tiene las propiedades básicas de un fichero. Un ejemplo sería el siguiente:
System.out.println("Propiedades de un Fichero");
Path p3 = Paths.get("c:\\temp\\ejemplo\\fichero.txt");
BasicFileAttributes attr = Files.readAttributes(p3, BasicFileAttributes.class);
System.out.println("Fecha de Creación: " + attr.creationTime());
System.out.println("Ultima Fecha de acceso: " + attr.lastAccessTime());
System.out.println("Última fecha de modificación: " + attr.lastModifiedTime());
System.out.println("isDirectorio: " + attr.isDirectory());
System.out.println("isFichero Regular: " + attr.isRegularFile());
System.out.println("isSymbolicLink: " + attr.isSymbolicLink());
System.out.println("size: " + attr.size());
Modificar propiedades fecha de creación del fichero
Es posible modificar las propiedades de tiempo de un fichero de esta manera:
long currentTime = System.currentTimeMillis();
FileTime ft = FileTime.fromMillis(currentTime);
Files.setLastModifiedTime(p3, ft);
System.out.println("Última fecha de modificación: " + attr.lastModifiedTime());
Permisos de los ficheros a través de Posix
Posix es un acrónimo de Portable Operating System Interface para Unix y sistemas operativos estándar, además de IEEE.
A través de la clase PosixFileAttributes.class y PosixFilesPermision podemos obtener los permisos de un fichero. Los métodos de la clase Posixfiles Permision son:
Métodos |
Definición |
fromString() | Acepta los String como permisos, devolviendo los permisos en su formato correspondiente. |
Podemos ver los permisos de un fichero , de la siguiente forma:
ToString() | Convierte los permisos a un String |
System.out.println("********Permisos fichero***********");
PosixFileAttributes attr2 =
Files.readAttributes(p3, PosixFileAttributes.class);
System.out.format("%s %s %s%n",
attr2.owner().getName(),
attr2.group().getName(),
PosixFilePermissions.toString(attr2.permissions()));
}
}
Modificar un Fichero o su Group Owner
Se puede dar permisos a un fichero a través de un usuario o de un grupo de usuarios.De tal manera, que con el método LookupPrincipalByName se puede dar permiso a un usuario concreto, o LookupPrincipalGroupName se da permisos a través de un grupo.
La forma sería de la siguiente manera:
GroupPrincipal grupo = p2.getFileSystem().getUserPrincipalLookupService()
.lookupPrincipalByGroupName("cursoJava");
Files.getFileAttributeView(p2, PosixFileAttributeView.class)
.setGroup(group);
Leer, escribir y crear ficheros
Nio2 permite además la manipulación de ficheros a través de la clase File y el método newBufferedReader que crea un objeto de tipo Buffered para generar entrada-salida.
Los pasos para hacer esto serían:
- Crear un Buffer
- rear Canales
- Utilizar la clase File
La clase BufferedReader tiene parámetros denominados OpenOptions donde indicamos el formato en el que se abre un fichero.
Tiene la siguientes posibilidades:
Métodos |
Definición |
WRITE | Abre el fichero en modo escritura |
APPEND | Permite añadir nuevas filas al fichero |
TRUNCATE_EXISTING |
Trunca el fichero a 0 bytes |
CREATE_ NEW |
Crea un nuevo fichero lanzando una excepción si ya existe. |
CREATE | Abre el fichero si existe y si no existe lo crea |
DELETE_ON_CLOSE | Borrar el fichero cuando el Stream es cerrado |
Escribir en ficheros
Existe la posiblidad de escribir en fichero a través del método write de la clase File. A write(path,buffer) se le pasa el Path y un array de bytes de tal manera que el resultado sería el siguiente:
byte[] buf = "esto es una prueba 2".getBytes();
Files.write(p3, buf);
Leer ficheros
Existe la posiblidad de escribir en fichero a través del método write de la clase File. A write(path,buffer) se le pasa el Path y un array de bytes de tal manera que el resultado sería el siguiente:
Charset charset = Charset.forName("US-ASCII");
try (BufferedReader reader = Files.newBufferedReader(p3, charset)) {
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
Creación de ficheros
Se puede crear un fichero vacío con un conjunto de atributos iniciales usando createFile(path,fileAttribut)e. Si el fichero existe se lanza una excepción. A continuación se muestra un ejemplo:
Path p4 = Paths.get("c:\\temp\\ejemplo\\fichero4.txt");
try {
Files.createFile(p4);
} catch (FileAlreadyExistsException x) {
System.err.format("Error el fichero existe");
} catch (IOException x) {
System.err.format("Error de permisos sobre el fichero");
}
Ficheros Acceso Aleatorio
De manera estándar y a través del paquete Java.io, también existe la posibilidad de acceder a los ficheros de manera no secuencial. La clase ByteBuffer proporciona métodos para mover el puntero y dintintas partes del fichero y la interface SeekableByteChannel que implementa la clase FileChanel proporciona métodos para leer y escribir de manera aleatoria. Algunos los métodos disponibles son los siguientes:
Métodos |
Definición |
position |
Retorna la posición actual del cursor |
Positon(long) | Modifica la posición |
Read(byteBuffer) | Lee los bytes del buffer |
Write(byteBuffer) | Escribe en el buffer |
Truncate(long) |
Trunca el fichero correspondiente. |
public class Prueba
{
public static void main(String[] args) throws IOException
{
RandomAccessFile File = new RandomAccessFile
("prueba.txt", "r");
FileChannel inChannel = File.getChannel();
ByteBuffer buff = ByteBuffer.allocate(1024);
while(inChannel.read(buffer) > 0)
{
buff.flip();
for (int i = 0; i < buff.limit(); i++)
{
System.out.print((char) buff.get());
}
buff.clear(); }
inChannel.close();
File.close();
}
}