Java NIO.2 a través de ejemplos

En la versión 7 de Java se introdujo el paquete java.nio.file, el cual supuso una importante mejora respecto al antiguo manejo de ficheros vía IO. Operaciones aparentemente tan sencillas como leer/escribir un archivo de texto en/desde un String suponían la escritura de varias líneas de código. De hecho, una librería prácticamente obligatoria cuando se tenía que hacer un uso importante de ficheros era Commons IO.

Se mostrarán a continuación varios ejemplos típicos de uso, donde se verá la potencia y sencillez de este paquete.

Crea un fichero vacío si aún no existe
[code language=»java»]
Path emptyFile = Paths.get(«/examples/emptyFile.txt»);
if (Files.notExists(emptyFile)) {
emptyFile = Files.createFile(Paths.get(«/examples/emptyFile.txt»));
}
[/code]

Lee el contenido de un fichero de texto a una cadena
[code language=»java»]
String content = new String(Files.readAllBytes(Paths.get(«/examples/sampleText.txt»)),
StandardCharsets.UTF_8);
System.out.println(content);
[/code]

Lee el contenido de un fichero de texto línea a línea
[code language=»java»]
List lines = Files.readAllLines(Paths.get(«/examples/sampleText.txt»),
StandardCharsets.UTF_8);
for (String line : lines) {
System.out.println(line);
}
[/code]

Escribe un String a un fichero de texto, sobreescribiéndolo si ya existiera
[code language=»java»]
String text = «Esto es una cadena de prueba»;
Files.write(Paths.get(«/examples/writeText.txt»), text.getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
[/code]

Escribe una lista de String a un fichero de texto, sobreescribiéndolo si ya existiera
[code language=»java»]
List textLines = Arrays.asList(«Línea 1», «Línea 2», «Línea 3»);
Files.write(Paths.get(«/examples/writeLines.txt»), textLines, StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
[/code]

Crear una estructura de directorios de forma recursiva. Si algún directorio ya existiera no lanzará excepción
[code language=»java»]
Files.createDirectories(Paths.get(«/examples/level1/level2/level3″));
[/code]

Tamaño en bytes de un directorio
[code language=»java»]
long size = Files.walk(Paths.get(«/examples»)).parallel().filter(p -> p.toFile().isFile())
.mapToLong(p -> p.toFile().length()).sum();
System.out.println(«Tamaño del directorio: » + size);
[/code]

Cuenta el número de ficheros de un directorio de forma recursiva
[code language=»java»]
long count = Files.walk(Paths.get(«/examples»)).parallel().filter(p -> !p.toFile().isDirectory()).count();
System.out.println(«Total de ficheros: » + count);
[/code]

Cuenta el número de ficheros no vacíos con ciertas extensiones leyendo solo dos niveles a partir del directorio principal
[code language=»java»]
long parcialCount = Files.walk(Paths.get(«/examples»), 2).parallel()
.filter(p -> p.toString().matches(«(?i).+\\.(txt|log|conf)$») && p.toFile().length() > 0L).count();
System.out.println(«Ficheros que cumplen con el filtro: » + parcialCount);
[/code]

Lista recursiva con los directorios contenidos en un directorio padre
[code language=»java»]
List dirs = Files.walk(Paths.get(«/examples»)).filter(Files::isDirectory).map(x -> x.toAbsolutePath())
.collect(Collectors.toList());
for (Path dir : dirs) {
System.out.println(«Ruta del directorio: «.concat(dir.toString()));
}
[/code]

Lista recursiva con los ficheros contenidos en un directorio
[code language=»java»]
List files = Files.walk(Paths.get(«/examples»))
.filter(Files::isRegularFile).map(x -> x.toAbsolutePath()).collect(Collectors.toList());
for (Path file : files) {
System.out.println(«Ruta del fichero: «.concat(file.toString()));
}
[/code]

Limpia el contenido de un directorio borrando de forma recursiva todos los ficheros contenidos en el mismo
[code language=»java»]
Files.walk(Paths.get(«/to_be_cleared»)).parallel().filter(p -> p.toFile().isFile()).forEach(File::delete);
[/code]

Borra de forma recursiva un directorio y todo su contenido
[code language=»java»]
Files.walk(Paths.get(«/to_be_deleted»)).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
[/code]

Copia un directorio con todo su contenido desde un origen a un destino
[code language=»java»]
Path from = Paths.get(«/examples/source_dir»);
Path dest = Paths.get(«/examples/dest_dir»);
try (Stream stream = Files.walk(from)) {
stream.forEachOrdered(source -> {
try {
Files.copy(source, dest.resolve(from.relativize(source)), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
e.printStackTrace();
}
});
}
[/code]

Mueve un directorio con todo su contenido
[code language=»java»]
Files.move(Paths.get(«/examples/source_dir»), Paths.get(«/examples/dest_dir»),
StandardCopyOption.REPLACE_EXISTING);
[/code]

Convierte de Path a File y de File a Path
[code language=»java»]
File file = onePath.toFile();
Path path = oneFile.toPath();
[/code]

Como se ha podido comprobar, el uso de esta nueva API permite navegar, leer y escribir ficheros, consultar sus atributos (fechas de creación, modificación, acceso, permisos…) copiar y mover ficheros o directorios, reconocer enlaces simbólicos, entrada/salida asíncrona y más funcionalidades que nos facilitarán enormemente el trabajo con ficheros y directorios sin falta de importar librerías externas.

VIERNES 21 DE AGOSTO DE 2020