Search code examples
javanio2java.nio.file

What is the difference between Files.list and Files.walkFileTree and Files.walk with maxdepth = 1?


If I want to do something with files only on the first level of the directory, is there a difference between using Files.list(...) or Files.walkFileTree(...) or Files.walk(...)?

Files.walkFileTree(directory, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        doSomething(file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        // log exc
        return FileVisitResult.CONTINUE;
    }
});

versus

Files.list(directory)
    .forEach(path -> {
        try {
            doSomething(path);
        } catch (IOException exc) {
            // log exc
        }
    });

versus

Files.walk(directory, 1)
    .forEach(path -> {
        try {
            doSomething(path);
        } catch (IOException exc) {
            // log exc
        }
});

Solution

  • Using following code as test, I got the hang of the issue. The main difference between walk* and list is that list(dir) gives a stream of files in the directory dir, while both walk* method walk the subtree of its argument including the root of subtree—the directory itself.

    The difference between walk and walkFileTree is that they supply different interfaces for walking the tree: walkFileTree takes FileVisitor, walk gives Stream<Path>.

    public class FilesTest {
        public static void main(String[] args) {
            final String pwd = System.getProperty("user.dir");
            System.out.println("Working Directory = " + pwd);
            Path dir = Paths.get(pwd);
            System.out.println("Files.walk");
            try (Stream<Path> stream = Files.walk(dir, 1)) {
                stream.forEach(path -> FilesTest.doSomething("walk", path));
            } catch (IOException e) {
                logException("walk", e);
            }
            System.out.println("Files.walkFileTree");
            try {
                Files.walkFileTree(dir, Collections.emptySet(), 1, new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        doSomething("visitFile", file);
                        return FileVisitResult.CONTINUE;
                    }
    
                    @Override
                    public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                        logException("visitFile", exc);
                        return FileVisitResult.CONTINUE;
                    }
                });
            } catch (IOException e) {
                logException("walkFileTree", e);
            }
            System.out.println("Files.list");
            try (Stream<Path> stream = Files.list(dir)) {
                stream.forEach(path -> FilesTest.doSomething("dir", path));
            } catch (IOException e) {
                logException("dir", e);
            }
        }
    
        private static void logException(String title, IOException e) {
            System.err.println(title + "\terror: " + e);
        }
    
        private static void doSomething(String title, Path file) {
            System.out.println(title + "\t: " + file);
        }
    }