Exploring a directory with the Java 8 Stream API
September 21, 2017 Leave a comment
We saw an example of using the Java 8 Stream API in File I/O in this post. We saw how the Files object was enhanced with the lines() method to open a line reader stream to a text file.
There are other enhancements related to streams that make is simple to explore a directory on your hard drive. The following code example will collect all folders and files within the c:\gitrepos folder and add them to an ArrayList:
Path gitReposFolderPath = Paths.get("c:\\gitrepos"); gitReposFolderPath.toFile().getName(); try (Stream<Path> foldersWithinGitReposStream = Files.list(gitReposFolderPath)) { List<String> elements = new ArrayList<>(); foldersWithinGitReposStream.forEach(p -> elements.add(p.toFile().getName())); System.out.println(elements); } catch (IOException ioe) { }
I got the following output:
[cryptographydotnet, dotnetformsbasedmvc5, entityframeworksixdemo, owinkatanademo, signalrdemo, singletondemoforcristian, text.txt, webapi2demo, windowsservicedemo]
The code returns both files and folders one level below the top directory, i.e. the “list” method does not dive into the subfolders. I put a text file into the folder – text.txt – just to test whether in fact all elements are returned.
Say you only need files – you can use the filter method:
foldersWithinGitReposStream.filter(p -> p.toFile().isFile()).forEach(p -> elements.add(p.toFile().getName()));
This will only collect text.txt.
Let’s try something slightly more complex. We’ll organise the elements within the directory into a Map of Boolean and List of Paths. The key indicates whether the group of files are directories or not. We can use the collect method that we saw in this post:
try (Stream<Path> foldersWithinGitReposStream = Files.list(gitReposFolderPath)) { Map<Boolean, List<Path>> collect = foldersWithinGitReposStream.collect(Collectors.groupingBy(p -> p.toFile().isDirectory())); System.out.println(collect); }
This prints the following:
{false=[c:\gitrepos\text.txt], true=[c:\gitrepos\cryptographydotnet, c:\gitrepos\dotnetformsbasedmvc5, c:\gitrepos\entityframeworksixdemo, c:\gitrepos\owinkatanademo, c:\gitrepos\signalrdemo, c:\gitrepos\singletondemoforcristian, c:\gitrepos\webapi2demo, c:\gitrepos\windowsservicedemo]}
So we successfully grouped the paths.
As mentioned above the “list” method goes only one level deep. The “walk” method in turn digs deeper and extracts sub-directories as well:
try (Stream<Path> foldersWithinGitReposStream = Files.walk(gitReposFolderPath)) { List<String> elements = new ArrayList<>(); foldersWithinGitReposStream.filter(p -> p.toFile().isFile()).forEach(p -> elements.add(p.toFile().getAbsolutePath())); System.out.println(elements); }
We can also instruct the walk method to go n levels down with an extra integer argument:
try (Stream<Path> foldersWithinGitReposStream = Files.walk(gitReposFolderPath, 3))
View all posts related to Java here.