2010-04-05 28 views
5

Prima di eseguire il debug della funzione ricorsiva con ritardo dell'ora: esiste un comando per ottenere sottodirectory? giveMeSubDirs(downToPath)?Java: come ottenere ricorsivamente tutte le sottodirectory?

// 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; 
} 

Sintesi sul codice:

  1. andare in profondità per l'albero delle directory possibile. Quando non c'è una dir in una dir, fermati, metti la dir sull'insieme, attraversa. Non controllare le dir nel set.
  2. Arrestare e restituire il set se si raggiunge il percorso di partenza.
  3. Ripetere i passaggi 1 e 2.

PREMESSA: la directory-struttura è finito e con una piccola quantità di dati.

+0

IMO è meglio andare top-down poi bottom-up (come nel mio soluzione qui di seguito :)). È più naturale in questo modo e non è necessario memorizzare i percorsi su livelli intermedi. – pajton

+0

Cosa stai cercando di fare? Stai cercando di elencare tutte le sottodirectory finché non raggiungi un certo livello? – OscarRyz

+1

Nel titolo si dice: "ricorsivamente" ma nel tuo codice non è ricorsivo? Stai cercando una soluzione ricorsiva o per una soluzione non ricorsiva? Qual è il nome completo per 'FileObject' è quello' javax.tools.FileObject' – OscarRyz

risposta

23

È possibile ottenere tutte le sottodirectory con il seguente frammento:

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

Questo diventa solo sottodirectory immediati, per recuperare tutti loro in modo ricorsivo si potrebbe scrivere:

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, più veloce di me! – Jack

+0

Thnx, supporto piuttosto insolito :-) – pajton

+0

Mi piace, molto pulito –

-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

Qualcosa non va nella compilazione: http://stackoverflow.com/questions/2581158/java-how-to-get-all-subdirs-recursively/2584464#2584464 – hhh

2

Un'altra versione con nessuna ricorsione e ordine alfabetico. Utilizza anche un Set per evitare loop (un problema nei sistemi Unix con collegamenti).

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

In realtà non si dovrebbe usare la classe java.util.Stack, come è rotto. Utilizzare invece ArrayDeque: Deque stack = new ArrayDeque (); – helpermethod

+0

Buona chiamata. Ho modificato il codice per usare Deques invece. – tucuxi

+0

Rotto come, per interesse? Mi stavo solo chiedendo :) –

1

Manca il codice di esempio ");" alla fine della dichiarazione. Il codice corretto dovrebbe essere:

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