2010-04-05 21 views
5

Antes de depurar la función recursiva de última hora de salida: ¿hay un comando para obtener subdirectorios? giveMeSubDirs(downToPath)?Java: ¿cómo obtener todos los subdires recursivamente?

// WARNING: RECURSION out of bound or too much data 
public HashSet<FileObject> getAllDirs(String path) { 
    HashSet<FileObject> checkedDirs = new HashSet<FileObject>(); 
    HashSet<FileObject> allDirs = new HashSet<FileObject>(); 

    String startingPath = path; 

    File fileThing = new File(path); 
    FileObject fileObject = new FileObject(fileThing); 

    for (FileObject dir : getDirsInDir(path)) { 

    // SUBDIR 

    while (!checkedDirs.contains(dir) 
     && !(getDirsInDir(dir.getFile().getParent()).size() == 0)) { 

     // DO NOT CHECK TOP DIRS if any bottom dir UNCHECKED! 

     while (uncheckedDirsOnLevel(path, checkedDirs).size() > 0) { 

     while (getDirsInDir(path).size() == 0 
      || (numberOfCheckedDirsOnLevel(path, checkedDirs)==getDirsInDir(path).size())) { 
      allDirs.add(new FileObject(new File(path))); 
      checkedDirs.add(new FileObject(new File(path))); 

      if(traverseDownOneLevel(path) == startingPath) 
      return allDirs; 

      //get nearer to the root 
      path = traverseDownOneLevel(path); 
     } 
     path = giveAnUncheckedDir(path, checkedDirs); 

     if (path == "NoUnchecked.") { 
      checkedDirs.add(new FileObject((new File(path)).getParentFile())); 
      break; 
     } 
     } 
    } 
    } 
    return allDirs; 
} 

Resumen sobre el código:

  1. ir tan profundo como para el árbol de directorios como sea posible. Cuando no hay un directorio en un directorio, deténgalo, coloque el directorio en el conjunto, recorra hacia arriba. No verifique los directorios en el conjunto.
  2. Detenga y devuelva el conjunto si llega a la ruta de inicio.
  3. Repita los pasos 1 y 2.

premisa: la estructura de directorios es finito y con una cantidad pequeña de datos.

+0

OMI es mejor ir de arriba hacia abajo y luego de abajo hacia arriba (como en mi solución a continuación :)). Es más natural de esta manera y no es necesario almacenar las rutas en niveles intermedios. – pajton

+0

¿Qué estás tratando de hacer? ¿Estás tratando de enumerar todos los subdirectorios hasta que alcances un cierto nivel? – OscarRyz

+1

En el título dice: "recursivamente" pero en su código no es recursivo? ¿Está buscando una solución recursiva o no recursiva? ¿Cuál es el nombre completo de 'FileObject' es' javax.tools.FileObject' – OscarRyz

Respuesta

23

Usted puede obtener todos los subdirectorios con el siguiente fragmento:

File file = new File("path"); 
File[] subdirs = file.listFiles(new FileFilter() { 
    public boolean accept(File f) { 
     return f.isDirectory(); 
    } 
}); 

Esto consigue sólo subdirectorios inmediatos, para recuperar todos ellos de forma recursiva se podría escribir:

List<File> getSubdirs(File file) { 
    List<File> subdirs = Arrays.asList(file.listFiles(new FileFilter() { 
     public boolean accept(File f) { 
      return f.isDirectory(); 
     } 
    })); 
    subdirs = new ArrayList<File>(subdirs); 

    List<File> deepSubdirs = new ArrayList<File>(); 
    for(File subdir : subdirs) { 
     deepSubdirs.addAll(getSubdirs(subdir)); 
    } 
    subdirs.addAll(deepSubdirs); 
    return subdirs; 
} 
+0

+1, ¡más rápido que yo! – Jack

+0

Thnx, apoyo bastante inusual :-) – pajton

+0

Me gusta, muy limpio –

-1
class DirFileFilter extends FileFilter { 
    boolean accept(File pathname) { 
    return pathname.isDirectory(); 
    } 
} 

DirFileFilter filter = new DirFileFilter(); 
HashSet<File> files = new HashSet<File>(); 

void rec(File root) { 
    // add itself to the list 
    files.put(root); 
    File[] subdirs = root.list(filter); 

    // bound of recursion: must return 
    if (subdirs.length == 0) 
    return; 
    else //this is the recursive case: can call itself 
    for (File file : subdirs) 
     rec(file); 
} 
+0

algo malo en su compilación: http://stackoverflow.com/questions/2581158/java-how-to-get-all-subdirs-recursively/2584464#2584464 – hhh

2

Otra versión con sin recursión, y orden alfabético. También usa un conjunto para evitar bucles (un problema en los sistemas Unix con enlaces).

public static Set<File> subdirs(File d) throws IOException { 
     TreeSet<File> closed = new TreeSet<File>(new Comparator<File>() { 
      @Override 
      public int compare(File f1, File f2) { 
       return f1.toString().compareTo(f2.toString()); 
      } 
     }); 
     Deque<File> open = new ArrayDeque<File>(); 
     open.push(d); 
     closed.add(d); 
     while (! open.isEmpty()) { 
      d = open.pop(); 
      for (File f : d.listFiles()) { 
       if (f.isDirectory() && ! closed.contains(f)) { 
        open.push(f); 
        closed.add(f); 
       } 
      } 
     } 
     return closed; 
    } 
+1

En realidad no debe usar la clase java.util.Stack, como está roto. Use ArrayDeque en su lugar: Deque stack = new ArrayDeque (); – helpermethod

+0

Buena llamada. He editado el código para usar Deques en su lugar. – tucuxi

+0

¿Qué tal, por interés? Me pregunto :) –

1

Falta el código de ejemplo anterior ");" al final de la declaración. El código correcto debería ser:

File file = new File("path"); 
    File[] subdirs = file.listFiles(new FileFilter() { 
     public boolean accept(File f) { 
      return f.isDirectory(); 
     } 
    }); 
Cuestiones relacionadas