Why use File filters
Many times it happens that only files of certain type are required. Type may mean files of certain extension or files having some definite characters in their name. There is no sense of showing or listing files which are of no use in that scenario. Consider an example where you need to upload image files to an application. When you click on Browse button, you would only be interested in viewing the list of image files(having .bmp, .jpg, .jpeg or .png extension) in the directory you select. It would be a hassle for you to select the desired file if all files in the directory are shown to you.
In programming terms, a filter is required when searching for a file in a directory and you know that the file is of certain type or having a certain name. By defining a filtering criteria, you can reduce the number of comparisons while finding the file specially if the directory has a large number of files. Besides you may also exclude nested directories during search if you know that the file resides in the selected directory.
How to use File filter in java
Java provides an interface java.io.FilenameFilter
which provides filtering capabilities using which, list of files can be filtered as per the given condition. This interface has an accept
method which takes 2 arguments; first is a java.io.File
object referring to the folder containing files and second is the name of the file in this folder. accept
method is implicitly called for every file in the folder on which the filter is applied and returns true
or false
as per the condition written in it. If the accept
method returns true
for a file, then the file is included in the search result else it is excluded from the results.
For applying a file filter, the first step is to create an instance of java.io.FilenameFilter
and implement its accept
method. Since java.io.FilenameFilter
is an interface, its instance cannot be created, hence we need to create a class which implements this interface and its accept
method as below :
import java.io.FilenameFilter;
public class CustomFileFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
// match file names with .docx extension
return name.endsWith(".docx");
}
}
Second step is applying the above filter when listing files in a directory. java.io.File
class has a listFiles
method which is used to get a list of all files in the directory represented by the File object. This class also has an overloaded listFiles
method which takes an object of type java.io.FilenameFilter
. We may directly pass an object of our CustomFileFilter class created above. This will call accept method on every file and listFiles
will only include those files in the list for which accept
will return true
. This means that files matching our criteria will be included in the list.
public class SearchFile {
public static void main(String[] args) {
// create a file object pointing to the directory
File directory = new File("D:\\codippa");
// pass an object of our file filter while listing files
File[] listOfMatchingFiles = directory.listFiles(new CustomFileFilter());
// iterate over the list of files
for (File file : listOfMatchingFiles) {
// print their path
System.out.println(file.getAbsolutePath());
}
}
}
Output
D:\codippa\abc.docx
D:\codippa\xyz.docx
D:\codippa\random.docx
Note that only files of .docx extension are returned in the list which exactly matches our filter criteria.
Other Methods of creating FilenameFilter
In the above example, a FilenameFilter was defined in a separate class which implements java.io.FilenameFilter
interface. There are a couple of other ways in which a FilenameFilter object can be created.
Method 1 : Using anonymous class
An anonymous class is one which does not have any name(or reference variable). Object of an anonymous class is created where it is required. Most common usage of an anonymous class is creating an instance of an interface and implementing its methods where they are needed as shown in the example below.
import java.io.FilenameFilter;
public class SearchFile {
public static void main(String[] args) {
// create a file object pointing to the directory
File directory = new File("D:\\codippa");
// create an object of file filter anonymously while listing files
File[] listOfMatchingFiles = directory.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// match file names with .docx extension
return name.endsWith(".docx");
}
});
// iterate over the list of files
for (File file : listOfMatchingFiles) {
// print their path
System.out.println(file.getAbsolutePath());
}
}
}
Method 2 : Creating FilenameFilter using Lambda expression
Since java.io.FilenameFilter
is a Functional interface, it can be implemented using Lambda expression. Using Lambda expression, a file filter can be defined directly inside listFiles
method. This reduces the file filter code significantly as shown in the code below
public class SearchFile {
public static void main(String[] args) {
// create a file object pointing to the directory
File directory = new File("D:\\codippa");
// create an object of file filter with filter defined using Lambda expression
File[] listOfMatchingFiles = directory.listFiles((dir, name) -> {
// match file names with .docx extension
return name.endsWith(".docx");
});
// iterate over the list of files
for (File file : listOfMatchingFiles) {
// print their path
System.out.println(file.getAbsolutePath());
}
}
}
Lambda expression enables us to implement the method declared in a Functional interface at the location where it is required. The implemented code should match with the method skeleton written in the interface. This means that the number of arguments should match with those in the interface and the return type of the implemented code should match with that of the method declared in the interface. Note that method name is used nowhere, it is implicitly invoked based on the context in which it is used.
Let’s tweak in
- File filters are frequently used in File selection dialogs in swing or javafx applications.
- File filters using Lambda expression can only be used starting from java 8.
- Lambda expression can only be utilized when the interface of the implemented method is a Functional interface.