7
votes

Java: Comment obtenir tous les sous-résidents récursives?

Avant de déboguer la fonction récursive tardive de l'heure tardive: y a-t-il une commande pour obtenir des sous-résidents? GivemesubDirs (Downtopath) CODE>?

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


4 commentaires

Imo il vaut mieux aller de haut en bas puis ascendant (comme dans ma solution ci-dessous :)). Il est plus naturel de cette façon et vous n'avez pas à stocker les chemins sur des niveaux intermédiaires.


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


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


@Ocar: Récursion de bas-haut. Pas Javax. *. S'il vous plaît, lisez l'avertissement, c'est incomplet.


8 Réponses :


2
votes

Non, il n'y a pas de fonctionnalité de ce type dans l'API standard Java. Mais il y a dans Apache Commons-io ; Si vous ne voulez pas l'inclure comme une bibliothèque, vous pouvez également Regardez le code source .


0 commentaires

26
votes

Vous pouvez obtenir tous les sous-didifiers avec le snippet suivant:

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


3 commentaires

@Hh arranges.Aslist renvoie apparemment une liste immuable. Nous devons donc construire une nouvelle arraylist mutable en plus de celui-ci.


Pourquoi avez-vous utilisé la liste au lieu de hashset ? Où pourriez-vous utiliser la commande?


Pas de raison particulière. Cependant, je ne pouvais pas utiliser arranges.aslist - il n'y a pas d'équivalent pour hashset . Liste Effectuez plus vite ici, je crois aussi.



-1
votes
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);
}

1 commentaires

Quelque chose ne va pas avec la compilation: Stackoverflow.com/Questtions/2581158/...



2
votes

Une autre version sans récursion et ordre alphabétique. Utilise également un ensemble 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;
    }


2 commentaires

Vous ne devriez en fait pas utiliser la classe Java.Util.stack, car elle est cassée. Utilisez ARRAYDEQUET à la place: DEQUE Stack = Nouveau ArrayDeque ();


@Chris: Il utilise la synchronisation par méthode sur la pop, la poussée (basée sur le vecteur, qui aime également ce type de synchronisation). C'est une performance inutile touchée si vous n'êtes pas multi-threading ce code et de nombreux scénarios multi-threading où vous avez besoin d'un grain de synchronisation plus grand. (J'ai regardé après le commentaire de l'assistant, comme j'avais la même question)



1
votes

Le code exemple 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();
      }
  });


0 commentaires

0
votes

Utilisation de la récursion:

private void getAllSubFoldersInPath(File path)
{
    File[] files=path.listFiles();
    try {
        for(File file: files)
        {
            if(file.isDirectory())
            {
                System.out.println("DIRECTORY:"+file.getCanonicalPath());
                getAllSubFoldersInPath(file);
            }
            else
            {
                System.out.println("FILE: "+file.getCanonicalPath());   
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}


0 commentaires

0
votes

Ceci est un code amélioré avec une approche Java 8. Ce code fonctionnera sur une base de récursion et trouvera les répertoires jusqu'à la dernière racine.

List<File> subdirs = Arrays.asList(file.listFiles(File::isDirectory));


0 commentaires

0
votes
  1. Obtenez tous les fichiers du fichier root sous forme de tableau (@see LISTFILES )
  2. Trier juste pour les annuaires en distinguant des fichiers et des répertoires (@See ISDirectory )
  3. Convertir (filtré) Array à partir des étapes 1 et 2 à la liste
  4. ajoutez tous les annuaires trouvés à la liste résultante
  5. Répétez cette motif pour chaque fichier de répertoires que vous avez trouvé à l'étape 1, avec une liste de résultat croissante
  6. à la fin, reportez la liste résultante

    Tout ce qui a mis dans une certaine magie de Lambda: xxx

    juste commencer par le fichier root (qui devrait être un répertoire) et une liste vide.

    NOTE: Étape 1 et 2 peut être combiné à un filtre (@See LISTFILES (filtre FileFilter) )


1 commentaires

C'est une bonne pratique pour expliquer la réponse avec la solution à Stackoverflow.