开发者

Java: how to get all subdirs recursively?

Before debugging the late-hour-out-of-bound-recursive-function: is there a command to get subdirs? giveMeSubDirs(downToPath)?

// 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(pa开发者_C百科th).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;
}

Summary about the code:

  1. Go as deep to the directory tree as possible. When there is no dir in a dir, stop, put the dir to the set, traverse up. Do not check dirs in the set.
  2. Stop and return the set if you reach the starting path.
  3. Repeat steps 1 and 2.

PREMISE: the directory-structure is finite and with a small data amount.


You can get all subdirs with the following snippet:

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

This gets only immediate subdirs, to retrieve all of them recursively you could write:

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


No, there is no such functionality in the Java standard API. But there is in Apache commons-io; if you don't want to include it as a library, you could also look at the source code.


Another version with no recursion, and alphabetical order. Also uses a Set to avoid loops (a problem in Unix systems with links).

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


The sample code above is missing ");" at the end of the statement. The correct code should be:

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


Using recursion:

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


This is an improved code with Java 8 approach. This code will run on a Recursion basis and find the directories until the last root.

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

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

If you want only immediate subdirectories list, try with the below line of code..

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


  1. Get all files from root file as array (@see listFiles)
  2. Sort just for directories by distinguishing between files & directories (@see isDirectory)
  3. Convert (filtered) array from step 1 & 2 to list
  4. Add all found directories to resulting list
  5. Repeat that pattern for each directory file you found in step 1, with growing resulting list
  6. At the end, return resulting list

All that put into some lambda magic:

private static List<File> getAllSubDirectories(File root, List<File> result) {
    List<File> currentSubDirs = Arrays.asList(Objects.requireNonNull(root.listFiles(File::isDirectory), "Root file has to be directory"));
    result.addAll(currentSubDirs);
    currentSubDirs.forEach(file -> getAllSubDirectories(file, result));
    return result;
}

Just start with root file (which should be a directory) and an empty list.

Note: Step 1 & 2 can be combined with a filter (@see listFiles(FileFilter filter))


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜