2010-04-05 4 views
5

Avant de déboguer la fonction recursive-out-of-bound-late-hour-out-of-bound: existe-t-il une commande pour obtenir des sous-répertoires? giveMeSubDirs(downToPath)?Java: comment obtenir récursivement tous les sous-répertoires?

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

Résumé sur le code:

  1. Aller aussi profond à l'arborescence de répertoires que possible. Quand il n'y a pas de dir dans un répertoire, arrêtez, placez le dir dans l'ensemble, passez en haut. Ne pas vérifier dirs dans l'ensemble.
  2. Arrêtez et renvoyez l'ensemble si vous atteignez le chemin de départ.
  3. Répétez les étapes 1 et 2.

HYPOTHÈSE: la structure des répertoires est fini et avec une petite quantité de données.

+0

l'OMI, il est préférable d'aller de haut en bas puis de bas en haut (comme dans ma solution ci-dessous :)). C'est plus naturel de cette façon et vous n'avez pas besoin de stocker les chemins sur les niveaux intermédiaires. – pajton

+0

Qu'essayez-vous de faire? Essayez-vous de lister tous les sous-répertoires jusqu'à ce que vous atteigniez un certain niveau? – OscarRyz

+1

Dans le titre dit: "récursivement" mais dans votre code n'est pas récursif? Vous recherchez une solution récursive ou non récursive? Quel est le nom complet de 'FileObject' est que' javax.tools.FileObject' – OscarRyz

Répondre

23

Vous pouvez obtenir tous les subdirs avec l'extrait suivant:

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

Ce ne reçoit que subdirs immédiat, pour récupérer tous vous pourriez récursive écrire:

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, plus rapide que moi! – Jack

+0

Thnx, support plutôt inhabituel :-) – pajton

+0

Je l'aime, très propre –

2

Non, il n'existe aucune fonctionnalité de ce type dans l'API standard Java. Mais il y a dans Apache commons-io; Si vous ne voulez pas l'inclure en tant que bibliothèque, vous pouvez également look at the source code.

-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

Quelque chose ne va pas avec la compilation: http://stackoverflow.com/questions/2581158/java-how-to-get-all-subdirs-recursively/2584464#2584464 – hhh

2

Une autre version avec pas de récursion, et l'ordre alphabétique. Utilise également un Set pour éviter les boucles (un problème dans les systèmes Unix avec des liens).

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

Vous ne devriez pas utiliser la classe java.util.Stack, comme il est cassé. Utilisez plutôt ArrayDeque: Deque stack = new ArrayDeque (); – helpermethod

+0

Bon appel. J'ai modifié le code pour utiliser Deques à la place. – tucuxi

+0

Broken comment, par intérêt? Je me demandais juste :) –

1

L'exemple de code ci-dessus est manquant ");" à la fin de la déclaration. Le code correct doit être:

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