Java: lista de archivos en un directorio

Muchas aplicaciones manejan archivos de alguna manera y la manipulación de archivos es uno de los conocimientos básicos en cualquier lenguaje de programación. Para manipular archivos,...

Introducción

Muchas aplicaciones manejan archivos de alguna manera y la manipulación de archivos es uno de los conocimientos básicos en cualquier lenguaje de programación.

Para manipular archivos, necesitamos saber dónde están ubicados. Tener una visión general de los archivos en un directorio es primordial si queremos lograr esto, especialmente si podemos realizar operaciones en ellos a través de la iteración. Hay varias formas de hacer esto en Java, que mostraremos a lo largo de este artículo.

En aras de la simplicidad, todos los ejemplos se escribirán para el siguiente árbol de archivos:

1
2
3
4
5
6
7
8
9
Programming
|-- minimax.c
|-- super_hack.py
|-- TODO.txt
`-- CodingMusic
    |-- Girl Talk - All Day.mp3
    |-- Celldweller - Frozen.mp3
    |-- Lim Taylor - Isn't It Wonderful.mp3
    `-- Radiohead - Everything in Its Right Place.mp3

Archivo.lista()

El método más simple para enumerar los nombres de archivos y carpetas en un directorio dado, sin atravesar los subdirectorios, es el método auxiliar .list(), que devuelve una matriz de Strings.

Hacemos esto usando el método .list() en una instancia de File:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public class Pathnames {

    public static void main(String[] args) {
        // Creates an array in which we will store the names of files and directories
        String[] pathnames;

        // Creates a new File instance by converting the given pathname string
        // into an abstract pathname
        File f = new File("D:/Programming");

        // Populates the array with names of files and directories
        pathnames = f.list();

        // For each pathname in the pathnames array
        for (String pathname : pathnames) {
            // Print the names of files and directories
            System.out.println(pathname);
        }
    }
}

Usando un ciclo simple para cada, iteramos a través de la matriz e imprimimos las Strings.

1
2
3
4
CodingMusic
minimax.c
super_hack.py
TODO.txt

Usando este enfoque, no se muestran todos los elementos en el directorio CodingMusic, y una desventaja de este enfoque es que realmente no podemos hacer nada con los archivos en sí. Sólo estamos recibiendo sus nombres. Es útil cuando solo queremos echar un vistazo a los archivos al pie de la letra.

Filtro de nombre de archivo

Otra cosa que podemos hacer con el método .list() es crear un FilenameFilter para devolver solo los archivos que queremos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
File f = new File("D:/Programming");

// This filter will only include files ending with .py
FilenameFilter filter = new FilenameFilter() {
        @Override
        public boolean accept(File f, String name) {
            return name.endsWith(".py");
        }
    };

// This is how to apply the filter
pathnames = f.list(filter);

Ejecutar este fragmento de código produciría:

1
super_hack.py

Archivo.listFiles()

Similar al método anterior, este puede usarse para devolver los nombres de archivos y directorios, pero esta vez los obtenemos como una matriz de objetos File, lo que nos da la capacidad de manipularlos directamente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Pathnames {
    public static void main(String args[]) {

        // try-catch block to handle exceptions
        try {
            File f = new File("D:/Programming");

            FilenameFilter filter = new FilenameFilter() {
                @Override
                public boolean accept(File f, String name) {
                    // We want to find only .c files
                    return name.endsWith(".c");
                }
            };

            // Note that this time we are using a File class as an array,
            // instead of String
            File[] files = f.listFiles(filter);

            // Get the names of the files by using the .getName() method
            for (int i = 0; i < files.length; i++) {
                System.out.println(files[i].getName());
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
}

Producción:

1
minimax.c

Ahora, profundicemos en el sistema de archivos usando la recursividad y algunos métodos más para usar en el objeto File:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ListFilesRecursively {
    public void listFiles(String startDir) {
        File dir = new File(startDir);
        File[] files = dir.listFiles();

        if (files != null && files.length > 0) {
            for (File file : files) {
                // Check if the file is a directory
                if (file.isDirectory()) {
                    // We will not print the directory name, just use it as a new
                    // starting point to list files from
                    listDirectory(file.getAbsolutePath());
                } else {
                    // We can use .length() to get the file size
                    System.out.println(file.getName() + " (size in bytes: " + file.length()+")");
                }
            }
        }
    }
    public static void main(String[] args) {
        ListFilesRecursively test = new ListFilesRecursively();
        String startDir = ("D:/Programming");
        test.listFiles(startDir);
    }
}

Producción:

1
2
3
4
5
6
7
Girl Talk - All Day.mp3 (size in bytes: 8017524)
Celldweller - Frozen.mp3 (size in bytes: 12651325)
Lim Taylor - Isn't It Wonderful.mp3 (size in bytes: 6352489)
Radiohead - Everything in Its Right Place.mp3 (size in bytes: 170876098)
minimax.c (size in bytes: 20662)
super_hack.py (size in bytes: 114401)
TODO.txt (size in bytes: 998)

Archivos.walk()

En Java 8 y versiones posteriores, podemos usar la clase java.nio.file.Files para llenar un Stream y usarlo para recorrer archivos y directorios, y al mismo tiempo recorrer recursivamente todos los subdirectorios.

Tenga en cuenta que en este ejemplo usaremos Expresiones Lambda:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class FilesWalk {
    public static void main(String[] args) {
        try (Stream<Path> walk = Files.walk(Paths.get("D:/Programming"))) {
            // We want to find only regular files
            List<String> result = walk.filter(Files::isRegularFile)
                    .map(x -> x.toString()).collect(Collectors.toList());

            result.forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Aquí, hemos llenado un Stream usando el método .walk(), pasando un argumento Paths. La clase Paths consta de métodos estáticos que devuelven una Path basada en un String URI, y usando una Path, podemos ubicar el archivo fácilmente.

Path, Paths, Files y muchas otras clases pertenecen al paquete java.nio, que se introdujo en Java 7 como una forma más moderna de representar archivos sin bloqueos.

Luego, usando el Marco de Colecciones, se genera una lista.

Ejecutar este fragmento de código producirá:

1
2
3
4
5
6
7
D:\Programming\Coding Music\Radiohead - Everything in Its Right Place.mp3
D:\Programming\Coding Music\Lim Taylor - Isn't It Wonderful.mp3
D:\Programming\Coding Music\Celldweller - Frozen.mp3
D:\Programming\Coding Music\Girl Talk - All Day.mp3
D:\Programming\minimax.c
D:\Programming\super_hack.py
D:\Programming\TODO.txt

Conclusión

El manejo de archivos de alguna manera es una tarea central para la mayoría de los lenguajes de programación, y esto incluye la capacidad de enumerar y encontrar archivos en el sistema de archivos. Para manipular archivos, necesitamos saber dónde están ubicados. Tener una visión general de los archivos en un directorio es primordial si queremos lograr esto, especialmente si podemos realizar operaciones en ellos a través de la iteración.

En este artículo, mostramos varias formas diferentes en Java de listar archivos en el sistema de archivos, utilizando enfoques tanto lineales como recursivos. s.

Licensed under CC BY-NC-SA 4.0