How to list files in a folder matching some criteria / How to use FileNameFilter in java

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

  1. File filters are frequently used in File selection dialogs in swing or javafx applications.
  2. File filters using Lambda expression can only be used starting from java 8.
  3. Lambda expression can only be utilized when the interface of the implemented method is a Functional interface.

Leave a Reply