Use of FilenameFilter
Asked Answered
V

5

25

I have a directory:

File dir = new File(MY_PATH);

I would like to list all the files whose name is indicated as integer numbers strings, e.g. "10", "20".
I know I should use:

dir.list(FilenameFilter filter);

How to define my FilenameFilter?

P.S. I mean the file name could be any integer string, e.g. "10" or "2000000" or "3452345". No restriction in the number of digits as long as the file name is a integer string.

Vernal answered 12/11, 2013 at 15:19 Comment(1)
I've never done this before but 10 seconds on google says that you should do new FileNameFilter() and then implement an anonymous inner class to choose what file names you should accept.Denumerable
P
39

You should override accept in the interface FilenameFilter and make sure that the parameter name has only numeric chars. You can check this by using matches:

String[] list = dir.list(new FilenameFilter() {
    @Override
    public boolean accept(File dir, String name) {
        return name.matches("[0-9]+");
    }
});
Putrefaction answered 12/11, 2013 at 15:25 Comment(2)
@OldCurmudgeon unless you cannot (e.g., prefix is coming as an input parameter)Guelph
is it possible if I change hte array type to File[] instead of String[]?Torero
U
9

preferably as an instance of an anonymous inner class passsed as parameter to File#list.

for example, to list only files ending with the extension .txt:

File dir = new File("/home");
String[] list = dir.list(new FilenameFilter() {
    @Override
    public boolean accept(File dir, String name) {
        return name.toLowerCase().endsWith(".txt");
    }
});

To list only files whose filenames are integers of exactly 2 digits you can use the following in the accept method:

return name.matches("\\d{2}");

for one or more digits:

return name.matches("\\d+");    

EDIT (as response to @crashprophet's comment)

Pass a set of extensions of files to list

class ExtensionAwareFilenameFilter implements FilenameFilter {

    private final Set<String> extensions;

    public ExtensionAwareFilenameFilter(String... extensions) {
        this.extensions = extensions == null ? 
            Collections.emptySet() : 
                Arrays.stream(extensions)
                    .map(e -> e.toLowerCase()).collect(Collectors.toSet());
    }

    @Override
    public boolean accept(File dir, String name) {
        return extensions.isEmpty() || 
            extensions.contains(getFileExtension(name));
    }

    private String getFileExtension(String filename) {
        String ext = null;
        int i = filename .lastIndexOf('.');
        if(i != -1 && i < filename .length()) {
            ext = filename.substring(i+1).toLowerCase();
        }
        return ext;
    }
}


@Test
public void filefilter() {
    Arrays.stream(new File("D:\\downloads").
        list(new ExtensionAwareFilenameFilter("pdf", "txt")))
            .forEach(e -> System.out.println(e));
}
Unreserve answered 12/11, 2013 at 15:21 Comment(4)
I need to filter out files to get only files with name contain integer numbers as string, no extention. E.g. "10" , "20"Vernal
How would you go about parameterizing the endsWith(parameter) call? If I wanted toto search for .txt or .pdf in certain circumstances, how would I do that?Domingadomingo
@Domingadomingo by create an own class implementing FilenameFilter and passing it the extensions you want to filter by. The argument for the File#list methos is no longer an anonymous class but an instance of the new class you have created. See code sample.Unreserve
Thanks A4L, I ended up doing something like the following:private final String filter; public FilterAwareFilenameFilter(String filter) { this.filter = filter; } @Override public boolean accept(File dir, String name) { return filter.toLowerCase().endsWith(this.filter); } // I don't know what I was doing before but it works now after your example!Domingadomingo
A
9

Since Java 8, you can simply use a lambda expression to specify your custom filter:

dir.list((dir1, name) -> name.equals("foo"));

In the above example, only files with the name "foo" will make it through. Use your own logic of course.

Accomplish answered 27/6, 2018 at 17:44 Comment(2)
how to specify a pattern here instead of equal() method?Isomagnetic
@gaurav just use the matches method like this: dir.list((dir1, name) -> name.matches("[0-9]+"));Gunstock
P
2

I do it as:

    File folder = new File(".");
    File[] listOfFiles = folder.listFiles();
    for (File file : listOfFiles) {
        if (file.isFile()) {
            if (file.toString().endsWith(".sql")) {
                System.out.println(file.getName());
            }
        }
    }
    System.out.println("End!!");
Peres answered 4/12, 2014 at 15:37 Comment(1)
Excellent Solution But you should add .toLowerCase() to your last "if" statement.Rabbinical
Q
1

Here's the what I wound up with. It uses a nice lambda expression that can be easily twisted to your own designs...

File folder = new File(FullPath);
String[] files = folder.list((lamFolder, lamName) -> lamName.matches("[0-9]+"));
if(files == null) {
    System.out.println("Stuff wrongly: no matching files found.");
} else {
    for(String file : files) {
        System.out.println("HOORAY: I found this "+ file);
    }
}
Quadrille answered 3/9, 2019 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.