¿Cómo puedo recursivamente lista de todos los archivos en un directorio en Java? ¿El marco de proporcionar alguna utilidad?

Vi un montón de hacky implementaciones. Pero ninguno de ellos en el marco o nio

  • Acabo de terminar los Resultados de la Prueba que proporcionar pruebas de rendimiento para muchas de las respuestas. Como era de esperar todos NIO respuestas a realizar mejor. El commons-io respuesta es claramente el peor artista con más de dos veces el largo plazo.
  • Java8 : Archivos.a pie ?
InformationsquelleAutor Quintin Par | 2010-01-13

21 Comentarios

  1. 288

    Java 8 proporciona un buen flujo de proceso para todos los archivos en un árbol.

    Files.walk(Paths.get(path))
            .filter(Files::isRegularFile)
            .forEach(System.out::println);

    Esto proporciona una forma natural para recorrer los archivos. Ya que es un flujo, se puede hacer todo buen flujo de operaciones en el resultado tal como límite, la agrupación, la cartografía, la salida temprana etc.

    ACTUALIZACIÓN: debo señalar que también hay Los archivos.encontrar que toma un BiPredicate que podría ser más eficiente si usted necesita para comprobar los atributos de archivo.

    Files.find(Paths.get(path),
               Integer.MAX_VALUE,
               (filePath, fileAttr) -> fileAttr.isRegularFile())
            .forEach(System.out::println);

    Tenga en cuenta que mientras que el JavaDoc escapa que este método podría ser más eficiente que Los archivos.a pie es idéntico, la diferencia en el rendimiento pueden ser observados si usted también está la recuperación de los atributos de archivo dentro de su filtro. En la final, si usted necesita el filtro en los atributos de uso Los archivos.encontrar, de lo contrario usar Los archivos.a pie, sobre todo porque hay sobrecargas y es más conveniente.

    PRUEBAS: Como se pide me ha proporcionado una comparación de rendimiento de muchas de las respuestas. Retirar el Github del proyecto que contiene los resultados y un caso de prueba.

    • Uno de esos ejemplos que muestran la magia de la programación funcional incluso para los principiantes.
    • ¿Cómo funciona el rendimiento de este comparar con pre-java 8 métodos? Mi actual directory traversal es demasiado lento y estoy en busca de algo que va a acelerar.
    • Estoy escribiendo algunas pruebas que contienen la mayoría de las variantes en las respuestas proporcionadas. Hasta ahora, parece que el uso de Files.walk con una serie paralela es el mejor, seguido de cerca por Files.walkFileTree que es sólo un poco más lento. El aceptó respuesta usando commons-io es por lejos el más lento por mis pruebas a ser 4 veces más lento.
    • Las pruebas están completos y un proyecto agregado a Github, échale un vistazo a los resultados. La respuesta corta es el uso de cualquier NIO del sabor de las respuestas ofrecidas.
    • He intentado la solución, pero me da una excepción Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException. ¿Cómo puedo corregirlo
    • ¿Cómo puedo obtener una lista actual de los archivos de este?
    • en lugar de forEach uso collect con un conjunto o lista de coleccionista como .collect(Collectors.toList()). Si usted puede evitar un colector en su lógica, el mejor como va a usar menos los objetos y de procesamiento puede ser más rápido.
    • Wow, no puede quitarle los ojos de esta hermosa código. ¿Quién habría pensado que un día de Java podría permitir la implementación de dichas operaciones en una sola línea.
    • estoy en lo cierto que por defecto los Ficheros.a pie() no seguir enlaces simbólicos? Si es así y uno quería seguir enlaces simbólicos, parece que el primer fragmento de código podría ser Files.walk(Paths.get(path), FileVisitOption.FOLLOW_LINKS)
    • Disculpas por el retraso en la respuesta de @MattPassell, estás en lo correcto. Hay una advertencia para el uso de este cuando una circular enlace que se encuentra, no terminarás con un bucle recursivo a pesar de que por desgracia se va a obtener un FileSystemLoopException de ser lanzado, que es envuelto en un UncheckedIOException
    • gracias, buen punto. En el punto en particular que lo estoy usando, la ruta de acceso inicial podría ser un enlace simbólico, pero a partir de ese punto hacia abajo, no lo es. Eso me permitió hacer algo como esto Path basePath = Files.isSymbolicLink(basePath) ? Files.readSymbolicLink(basePath) : basePath; y, a continuación, recorrer el árbol sin vínculos siguientes. 🙂
    • de forEach uso recoger» lo sentimos pero todavía estoy claro. Llamar .collect(stagingFileList::add) en el flujo resultante de ese código se me Collector<Path,A,R> is not a functional interface en la colecta para el parámetro. Este flujo de material es fresco, pero no estoy completamente seguro de lo que estoy mirando ya para solucionarlo.
    • Esto es lo que estoy intentando– Files.find( Paths.get(path), Integer.MAX_VALUE, (filePath, fileAttr) -> fileAttr.isRegularFile()) .collect(list::add);
    • lo que estás buscando es un coleccionista, lo que ha dado es un método de referencia. Lista reemplazar::agregar con Collectors.toList()
    • Atento a este tema: bugs.openjdk.java.net/browse/JDK-8039910 Más info aquí: stackoverflow.com/questions/22867286/…
    • Los archivos.a pie se ve bien, pero muy a menudo es inútil…. se levanta una excepción si usted no tiene un acceso a un archivo… y no pasó nada…

  2. 158

    FileUtils han iterateFiles y listFiles métodos. Darles una oportunidad. (de commons-io)

    Editar: puede marque aquí para un punto de referencia de los diferentes enfoques. Parece que el commons-io enfoque es lento, por lo que elegir algunas de las más rápidas queridos desde aquí (si es importante)

    • FYI/TLDR: si sólo quieres la lista de todos los archivos de forma recursiva, sin filtros, hacer FileUtils.listFiles(dir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE), donde dir es un Archivo objeto que señala el directorio base.
    • Usted puede ser que desee considerar el uso de listFilesAndDirs(), como listFiles() no devuelve las carpetas vacías.
    • Mirando el FileUtils código, creo que vould ser FileUtils.listFiles(dir, true, true). el uso de FileUtils.listFiles(dir, null, true) lanzará una Excepción, mientras que FileUtils.listFiles(dir, true, null) mostrará la lista de todos los archivos sin necesidad de buscar en subdirectorios.
    • Cómo sobre un JDK de la biblioteca nativa? Puedo implementar esta fácil, pero yo simplemente ser C&P desde otros lugares
    • Me voy a poner algunas pruebas juntos, pero hasta el momento esto parece ser la realización de 4 veces más lento que el de la utilización de JDK8 o JDK7 alternativas. Enlaces simbólicos también resultar problemática con este enfoque, especialmente cuando se vinculan a los directorios más alto en el árbol, esto hace que el método para no volver jamás, esto puede ser evitado mediante la manipulación del filtro, pero lamentablemente los enlaces simbólicos en sí no obtener visitado incluso como un archivo.
  3. 132

    //Listo para ejecutar

    import java.io.File;
    
    public class Filewalker {
    
        public void walk( String path ) {
    
            File root = new File( path );
            File[] list = root.listFiles();
    
            if (list == null) return;
    
            for ( File f : list ) {
                if ( f.isDirectory() ) {
                    walk( f.getAbsolutePath() );
                    System.out.println( "Dir:" + f.getAbsoluteFile() );
                }
                else {
                    System.out.println( "File:" + f.getAbsoluteFile() );
                }
            }
        }
    
        public static void main(String[] args) {
            Filewalker fw = new Filewalker();
            fw.walk("c:\" );
        }
    
    }
    • Sólo ten en cuenta que para enlaces simbólicos que apuntan a un camino más en el camino de la jerarquía hará que el método no tener fin. Considere la posibilidad de un camino con un enlace simbólico que apunta a -> ..
    • Esto es esencialmente una mala implementación de Archivos.walkFileTree. Yo recomendaría que la gente busca en los Archivos.walkFileTree en lugar de intentar rodar a ti mismo… tiene control para el problema exacto @BrettRyan señaló.
    • Gracias por incluir a importar java.io.Archivo;. Muchos ejemplos olvide incluir el espacio de nombres de cosas o incluso tipo de cosas a hacer el ejemplo de un punto de partida en un viaje de descubrimiento. Aquí este ejemplo está listo para ejecutar. Gracias.
  4. 66

    Java 7 habrá ha Los archivos.walkFileTree:

    Si usted proporciona un punto de partida y un archivo de visitante, que se invocan diversos métodos en el archivo de visitante cuando camina a través de los archivos en el árbol de archivos. Esperamos que la gente utilice esta opción si se está desarrollando una copia recursiva, recursivo mover, recursivo eliminar, o una operación recursiva que establece los permisos o realiza otra operación en cada uno de los archivos.

    Ahora hay toda una Oracle tutorial sobre esta cuestión.

  5. 25

    No externo de las bibliotecas necesarias.

    Devuelve una Colección así que usted puede hacer lo que quiera con él después de la llamada.

    public static Collection<File> listFileTree(File dir) {
        Set<File> fileTree = new HashSet<File>();
        if(dir==null||dir.listFiles()==null){
            return fileTree;
        }
        for (File entry : dir.listFiles()) {
            if (entry.isFile()) fileTree.add(entry);
            else fileTree.addAll(listFileTree(entry));
        }
        return fileTree;
    }
    • sencillo y limpio
  6. 17

    Me gustaría ir con algo como:

    public void list(File file) {
        System.out.println(file.getName());
        File[] children = file.listFiles();
        for (File child : children) {
            list(child);
        }
    }

    El Sistema.a cabo.println está ahí para indicar a hacer algo con el archivo. no hay necesidad de diferenciar entre archivos y directorios desde un archivo normal simplemente tendrá cero niños.

    • A partir de la documentación de listFiles(): «Si este resumen, una ruta no denota un directorio, entonces este método devuelve null
    • Variante mejorada public static Colección<Archivo> listFileTree(Archivo dir) { if (null == dir || !dir.isDirectory()) { return Colecciones.emptyList(); } Set final<Archivo> fileTree = new HashSet<Archivo>(); for (Archivo de entrada : dir.listFiles()) { if (entrada.isFile()) { fileTree.agregar(entrada); } else { fileTree.addAll(listFileTree(entrada)); } } return fileTree; }
    • Para mí esta es la más concisa respuesta que es recursivo.
  7. 13

    Prefiero utilizar una cola de más de recursividad para este tipo de simple el recorrido se:

    List<File> allFiles = new ArrayList<File>();
    Queue<File> dirs = new LinkedList<File>();
    dirs.add(new File("/start/dir/"));
    while (!dirs.isEmpty()) {
      for (File f : dirs.poll().listFiles()) {
        if (f.isDirectory()) {
          dirs.add(f);
        } else if (f.isFile()) {
          allFiles.add(f);
        }
      }
    }
    • Pero el algoritmo no se puede imprimir con sangría de salida. Directorios y archivos están en mal estado. Alguna solución?
  8. 12

    sólo tienes que escribir tú mismo usando recursividad simple:

    public List<File> addFiles(List<File> files, File dir)
    {
        if (files == null)
            files = new LinkedList<File>();
    
        if (!dir.isDirectory())
        {
            files.add(dir);
            return files;
        }
    
        for (File file : dir.listFiles())
            addFiles(files, file);
        return files;
    }
    • Por favor! deje que la persona que llama inicializar la lista de archivos por lo que no se tiene que comprobar su nulidad cada momento. Si desea crear un segundo (público), método que crea la lista, llama a este método interno y devuelve la lista completa.
    • lo que sea. una verificación null no es muy caro, la conveniencia + preferencias personales aparte creo que voy a coger el punto.
    • Puede usted explicar muestra un poco más?
  9. 8

    Con Java 7 se puede utilizar la siguiente clase:

    import java.io.IOException;
    import java.nio.file.FileVisitResult;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.SimpleFileVisitor;
    import java.nio.file.attribute.BasicFileAttributes;
    
    public class MyFileIterator extends SimpleFileVisitor<Path>
    {
        public MyFileIterator(String path) throws Exception
        {
            Files.walkFileTree(Paths.get(path), this);
        }
    
        @Override
        public FileVisitResult visitFile(Path file,
                BasicFileAttributes attributes) throws IOException
        {
            System.out.println("File: " + file);
            return FileVisitResult.CONTINUE;
        }
    
        @Override
        public FileVisitResult preVisitDirectory(Path dir,
                BasicFileAttributes attributes) throws IOException
        {
            System.out.println("Dir: " + dir);
            return FileVisitResult.CONTINUE;
        }
    }
  10. 7

    Creo que debería hacer el trabajo:

    File dir = new File(dirname);
    String[] files = dir.list();

    De esta manera usted tiene archivos y directorios. Ahora el uso de la recursividad y hacer lo mismo para dirs (File clase tiene isDirectory() método).

  11. 7

    Este código está listo para ejecutar

    public static void main(String... args) {
        File[] files = new File("D:/").listFiles();
        if (files != null) 
           getFiles(files);
    }
    
    public static void getFiles(File[] files) {
        for (File file : files) {
            if (file.isDirectory()) {
                getFiles(file.listFiles());
            } else {
                System.out.println("File: " + file);
            }
        }
    }
  12. 6

    En Java 8, ahora podemos usar los Archivos de utilidad a pie de un árbol de archivos. Muy simple.

    Files.walk(root.toPath())
          .filter(path -> !Files.isDirectory(path))
          .forEach(path -> System.out.println(path));
  13. 4

    Aparte de la recursivo recorrido uno puede utilizar un Visitante enfoque basado en así.

    A continuación el código se utiliza Visitante enfoque basado en el recorrido de la misma.Se espera que la entrada al programa es el directorio raíz para recorrer.

    public interface Visitor {
    void visit(DirElement d);
    void visit(FileElement f);
    }
    public abstract class Element {
    protected File rootPath;
    abstract void accept(Visitor v);
    @Override
    public String toString() {
    return rootPath.getAbsolutePath();
    }
    }
    public class FileElement extends Element {
    FileElement(final String path) {
    rootPath = new File(path);
    }
    @Override
    void accept(final Visitor v) {
    v.visit(this);
    }
    }
    public class DirElement extends Element implements Iterable<Element> {
    private final List<Element> elemList;
    DirElement(final String path) {
    elemList = new ArrayList<Element>();
    rootPath = new File(path);
    for (File f : rootPath.listFiles()) {
    if (f.isDirectory()) {
    elemList.add(new DirElement(f.getAbsolutePath()));
    } else if (f.isFile()) {
    elemList.add(new FileElement(f.getAbsolutePath()));
    }
    }
    }
    @Override
    void accept(final Visitor v) {
    v.visit(this);
    }
    public Iterator<Element> iterator() {
    return elemList.iterator();
    }
    }
    public class ElementWalker {
    private final String rootDir;
    ElementWalker(final String dir) {
    rootDir = dir;
    }
    private void traverse() {
    Element d = new DirElement(rootDir);
    d.accept(new Walker());
    }
    public static void main(final String[] args) {
    ElementWalker t = new ElementWalker("C:\\temp");
    t.traverse();
    }
    private class Walker implements Visitor {
    public void visit(final DirElement d) {
    System.out.println(d);
    for(Element e:d) {
    e.accept(this);
    }
    }
    public void visit(final FileElement f) {
    System.out.println(f);
    }
    }
    }
  14. 3

    Puede utilizar el siguiente código para obtener una lista de los archivos de la carpeta específica o de un directorio de forma recursiva.

    public static void main(String args[]) {
    recusiveList("D:");
    }
    public static void recursiveList(String path) {
    File f = new File(path);
    File[] fl = f.listFiles();
    for (int i = 0; i < fl.length; i++) {
    if (fl[i].isDirectory() && !fl[i].isHidden()) {
    System.out.println(fl[i].getAbsolutePath());
    recusiveList(fl[i].getAbsolutePath());
    } else {
    System.out.println(fl[i].getName());
    }
    }
    }
    • para mí funcionaba a la perfección… gracias
  15. 1

    No recursivo BFS con una única lista (ejemplo concreto es la búsqueda de *.archivos eml):

        final FileFilter filter = new FileFilter() {
    @Override
    public boolean accept(File file) {
    return file.isDirectory() || file.getName().endsWith(".eml");
    }
    };
    //BFS recursive search
    List<File> queue = new LinkedList<File>();
    queue.addAll(Arrays.asList(dir.listFiles(filter)));
    for (ListIterator<File> itr = queue.listIterator(); itr.hasNext();) {
    File file = itr.next();
    if (file.isDirectory()) {
    itr.remove();
    for (File f: file.listFiles(filter)) itr.add(f);
    }
    }
  16. 1

    Mi versión (por supuesto que podría haber utilizado el construido en pie en Java 8 😉 ):

    public static List<File> findFilesIn(File rootDir, Predicate<File> predicate) {
    ArrayList<File> collected = new ArrayList<>();
    walk(rootDir, predicate, collected);
    return collected;
    }
    private static void walk(File dir, Predicate<File> filterFunction, List<File> collected) {
    Stream.of(listOnlyWhenDirectory(dir))
    .forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction)));
    }
    private static File[] listOnlyWhenDirectory(File dir) {
    return dir.isDirectory() ? dir.listFiles() : new File[]{};
    }
    private static List<File> addAndReturn(List<File> files, File toAdd, Predicate<File> filterFunction) {
    if (filterFunction.test(toAdd)) {
    files.add(toAdd);
    }
    return files;
    }
  17. 1

    Aquí una sencilla pero perfectamente solución de trabajo utilizando recursion:

    public static List<Path> listFiles(String rootDirectory)
    {
    List<Path> files = new ArrayList<>();
    listFiles(rootDirectory, files);
    return files;
    }
    private static void listFiles(String path, List<Path> collectedFiles)
    {
    File root = new File(path);
    File[] files = root.listFiles();
    if (files == null)
    {
    return;
    }
    for (File file : files)
    {
    if (file.isDirectory())
    {
    listFiles(file.getAbsolutePath(), collectedFiles);
    } else
    {
    collectedFiles.add(file.toPath());
    }
    }
    }
  18. 1
        private void fillFilesRecursively(File file, List<File> resultFiles) {
    if (file.isFile()) {
    resultFiles.add(file);
    } else {
    for (File child : file.listFiles()) {
    fillFilesRecursively(child, resultFiles);
    }
    }
    }
  19. 1

    Se me ocurrió esto para la impresión de todos los archivos o nombres de archivo de forma recursiva.

    private static void printAllFiles(String filePath,File folder) {
    if(filePath==null) {
    return;
    }
    File[] files = folder.listFiles();
    for(File element : files) {
    if(element.isDirectory()) {
    printAllFiles(filePath,element);
    } else {
    System.out.println(" FileName "+ element.getName());
    }
    }
    }
  20. 0

    Ejemplo salidas *.los archivos csv en el directorio de búsqueda recursiva Subdirectorios utilizar los Archivos.find() de java.nio:

    String path = "C:/Daten/ibiss/ferret/";
    logger.debug("Path:" + path);
    try (Stream<Path> fileList = Files.find(Paths.get(path), Integer.MAX_VALUE,
    (filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toString().endsWith("csv"))) {
    List<String> someThingNew = fileList.sorted().map(String::valueOf).collect(Collectors.toList());
    for (String t : someThingNew) {
    t.toString();
    logger.debug("Filename:" + t);
    }
    }

    La publicación de este ejemplo, como yo tenía problemas para entender cómo pasar el nombre del archivo de parámetros en el #1 ejemplo dado por Bryan, usando foreach en Flujo-resultado –

    Espero que esto ayude.

  21. 0

    Basado en el apilador de respuesta. Aquí es una solución de trabajo en JSP sin ningún tipo de bibliotecas externas así que usted puede colocar casi en cualquier lugar en el servidor:

    <!DOCTYPE html>
    <%@ page session="false" %>
    <%@ page import="java.util.*" %>
    <%@ page import="java.io.*" %>
    <%@ page contentType="text/html; charset=UTF-8" %>
    <%!
    public List<String> files = new ArrayList<String>();
    /**
    Fills files array with all sub-files.
    */
    public void walk( File root ) {
    File[] list = root.listFiles();
    if (list == null) return;
    for ( File f : list ) {
    if ( f.isDirectory() ) {
    walk( f );
    }
    else {
    files.add(f.getAbsolutePath());
    }
    }
    }
    %>
    <%
    files.clear();
    File jsp = new File(request.getRealPath(request.getServletPath()));
    File dir = jsp.getParentFile();
    walk(dir);
    String prefixPath = dir.getAbsolutePath() + "/";
    %>

    Entonces usted acaba de hacer algo como:

        <ul>
    <% for (String file : files) { %>
    <% if (file.matches(".+\\.(apk|ipa|mobileprovision)")) { %>
    <li><%=file.replace(prefixPath, "")%></li>
    <% } %>
    <% } %>
    </ul>
    • Mientras que probablemente funciona, la pregunta es acerca de exploración de archivos, no de representación de hojear los archivos. Mejor exponer su algoritmo como tal, no es una práctica recomendada para incrustar la lógica de negocio dentro de una JSP.
    • Eso depende de lo que usted está haciendo. En una empresa de tamaño de la aplicación que usted está absolutamente en lo cierto. Si sólo necesita esto como una gota en un simple, independiente listado, entonces esto está perfectamente bien.

Dejar respuesta

Please enter your comment!
Please enter your name here