-1

Here is my actual code, which works perfectly :
String sHomeDir is my only folder where to start the scan
String sExt is the only extension to search for

try (Stream<Path> walk = Files.walk(Paths.get(sHomeDir)))
{
    List<String> result = walk.map(x -> x.toString())
        .filter(f -> f.endsWith(sExt)).collect(Collectors.toList());
    ...
} catch (IOException e) {
   e.printStackTrace();
}

Is it possible to rewrite that, in order to use :
- Multiple folders to scan (with subtree)
- Multiple file extensions to search for

Mureinik
  • 297,002
  • 52
  • 306
  • 350
Cruxial
  • 41
  • 4

2 Answers2

1

To handle multiple directories, you can stream them and flatmap them to a single stream of Paths. To handle multiple extensions, you just need to check the file against them all:

public static List<String> multiWalk
    (Collection<String> directories, Collection<String> extensions) {

    return directories.stream()
                      .flatMap(d -> {
                          try {
                              return Files.walk(Paths.get(d));
                          } catch (IOException e) {
                              return Stream.empty();
                          }
                      })
                      .map(Object::toString)
                      .filter(f -> extensions.stream().anyMatch(f::endsWith))
                      .collect(Collectors.toList());
}
SpencerPark
  • 3,298
  • 1
  • 15
  • 27
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • Hi @Mureinik, thank you for the proposal. I had to modify the flatmap section like this : `.flatMap(new Function>() { @Override public Stream extends Path> apply(String d) { try { return Files.walk(Paths.get(d)); } catch (IOException ex) { Stream.empty(); } return null; } })` – Cruxial Mar 17 '20 at 19:32
  • Because compiler says : lambda body is neither value nor void compatible... – Cruxial Mar 17 '20 at 19:39
  • Or better ... add the 'return null;' statement. I edited your code – Cruxial Mar 17 '20 at 19:43
  • 1
    @Cruxial Most likely Mureinik meant to use `return Stream.empty()` in the catch block, though personally I'd throw an `UncheckedIOException`. – Slaw Mar 17 '20 at 22:13
  • Yup, I missed the `return` there. Thanks for the edit! – Mureinik Mar 18 '20 at 05:23
0

I wanted to use the FilenameFilter used with the "File.list()"-method. I found a sample here.

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;

/**
 * 
 * @see: https://stackoverflow.com/questions/5751335/using-file-listfiles-with-filenameextensionfilter
 * 
 * <h3>setup filter like:</h3>
 * private static final ExtensionsFilenameFilter IMAGE_FILTER = <br/>
      new ExtensionsFilenameFilter(".png", ".jpg", ".bmp"); 
 * 
 */
public class ExtensionsFilenameFilter implements FilenameFilter {
    
    private char[][] extensions;

    public ExtensionsFilenameFilter(String... extensions)
    {
        int length = extensions.length;
        this.extensions = new char[length][];
        for (String s : extensions)
        {
            this.extensions[--length] = s.toCharArray();
        }
    }

    @Override
    public boolean accept(File dir, String name) {
        char[] path = name.toCharArray();
        for (char[] extension : extensions)
        {
            if (extension.length > path.length)
            {
                continue;
            }
            int pStart = path.length - 1;
            int eStart = extension.length - 1;
            boolean success = true;
            for (int i = 0; i <= eStart; i++)
            {
                if ((path[pStart - i] | 0x20) != (extension[eStart - i] | 0x20))
                {
                    success = false;
                    break;
                }
            }
            if (success)
                return true;
        }
        return false;
    }

}

Then I walk all pathes below a rootpath by:

public void walkList(String path) throws IOException {
    List<String> imagefiles = new ArrayList<>();
    Files.walk(Paths.get(path))
    .filter(Files::isDirectory)
    .map(walkPath -> {
        List<String> pathnames = new ArrayList<>();
        List<String> filenames = Arrays.asList(walkPath.toFile().list(new ExtensionsFilenameFilter("jpg", "tif", "bmp")));
        filenames.forEach(fn -> {
            pathnames.add(String.format("%s/%s", walkPath.toFile().toString(), fn));
        });
        return pathnames;
    })
    .forEach(imagefiles::addAll);

    imagefiles.forEach(System.out::println);
}
Ulrich
  • 715
  • 2
  • 7
  • 25