Custom File Filtering Using Java File Choosers

AID: 351
  • Status: Published

5600 points

  • By
  • TypeTutorial
  • Posted on2008-12-16 at 09:51:11
INTRODUCTION

Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.  

However, when your application has visual components, it might be a good idea to allow the user to select a file in a way similar to the Internet Browser's file choosers.

In a simple scenario, the usage of javax.swing.JFileChooser is all that is necessary to allow the user to browse the files and folders of the underlying Operating System.  But in most projects, the files that should be selected should have some specific properties - its location might be predefined, it might be restricted by size or by name, etc.  One option to solve these cases would be to allow the user to select any file or directory and then to check if this file/directory meets the requirements, notifying user for those that do not.  But a much better approach would be to show the user only the files that they can select from in the first place.

The following sections will take us through some code showing how the JFileChooser can be used in these more complicated scenarios.  Consequently, since every time a JFileChooser is used, a hidden object - a FileFilter - is used also. This FileFilter is responsible for deciding which files are to be shown in the UI. Therefore, this article will show you how to create your own FileFilters.

  • Adding a Custom File Filter.
  • Custom File Filtering: Using Anonymous FileFilter Implementation.
  • Custom File Filtering: Using Named FileFilter Implementation.
  • Wrapping Things Up.



PRE-REQUISITES

This article is for beginner Java programmers, so don't worry as the only pre-requisites are the Java Developer's Kit (JDK), version 1.2 or higher, and a development tool of your choice.  Although, notepad is good enough, I would recommend an Integrated Development Environment (IDE) such as NetBeans or Eclipse to ease the trivial tasks of compilation and to provide niceties like color-coded syntax.  For a balance between color-coding and the purity of using notepad, TextPad or NotePad++ would be a nice alternative on Windows.  Downloads for some editors will be listed at the end of the article; however, please feel free to use whichever tools you are comfortable with.


1

Adding a Custom File Filter.


To begin our journey, we will examine the basics of properly adding a FileFilter to JFileChooser.

JFileChooser chooser = new JFileChooser();

// using in-line definition (anonymous) implementation.
chooser.addChoosableFileFilter(new FileFilter() {

    @Override
    public boolean accept(File arg0) {
        return true;
    }

    @Override
    public String getDescription() {
        return null;
    }
    
});

// using a pre-defined (named) class implementation.
chooser.addChoosableFileFilter(
   new SomeCustomFileFilter()
);
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:

Select allOpen in new window


As shown in the code above, the key method is addChoosableFileFilter(javax.swing.filechooser.FileFilter).  How we construct the FileFilter is a matter of implementation choice; however, accept(java.io.File) and getDescription() are always required to be implemented.  The former should return true if the file meets the filter criteria, while the latter is the description that is shown in the "Files of type:" drop-down list.

Another key to truly having a custom file filter is to turn off the standard "All Files" files of type choice:

chooser.setAcceptAllFileFilterUsed(false);
                                    
1:

Select allOpen in new window




2

Custom File Filtering: Using Anonymous FileFilter Implementation.


Now let's take a look at a very simplified example using rich text format (RTF) file filter.

We'll start with the getDescription() since it doesn't take much to create:

public String getDescription() {
    return "*.RTF";
}
                                    
1:
2:
3:

Select allOpen in new window


Tired yet!

That was a lot of code, I know. :)

So considering that should be self explanatory, let's add our accept(File) method:

public boolean accept(File f) {

    // Allow directories to be seen.
    if (f.isDirectory()) return true;
    
    // Allows files with .rtf extension to be seen.
    if(f.getName().toLowerCase().endsWith(".rtf"))
        return true;

    // Otherwise file is not shown.
    return false;
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:

Select allOpen in new window


Voilà !

Not much harder, but a little more to talk about here.

When choosing a file, we want to be able to browse directories in order to traverse them; therefore, we have to ensure that we return true for all folders.

Then for files, we are going to do our filtering based on simple inspection of the file extension.  This is obviously not sufficient all the time especially when programming for systems that may not use file extensions in the same way Windows does (e.g., Macs at least the older ones I have dealt with used resource and data forks and did not require an extension in the filename).  However, we will stick with this example as it is very straight-forward.

Since Java is case-sensitive, for our simple test, we have to get lower case version of file name and check if it ends with desired extension (also in lower case).

f.getName().toLowerCase().endsWith(".rtf")
                                    
1:

Select allOpen in new window



As an alternative, we could also parse the file extension from f.getName(), store it in a variable called "fileext" for example, and then utilize the String object's equalsIgnoreCase() method.

".rtf".equalsIgnoreCase(fileext)
                                    
1:

Select allOpen in new window



Checkpoint: write your own program using JFileChooser and an anonymous implementation of FileFilter.  An example is attached for your reference, but challenge yourself before taking a look.

Challenge: can you alter your program to only allow ".rtf" files that begin with the word "article"?



3

Custom File Filtering: Using Named FileFilter Implementation.


Let's take this a little further; we will now add more multiple options to the "Files of type:" drop-down list.  Expanding on our simple anonymous class for filtering files based on the extension, we will now create a named implementation of javax.swing.filechooser.FileFilter.  To keep things simple, the below is an example of a nested class that could reside in the same compilation unit we created above (e.g., see FileChooserExample.java in the Appendix A).

Extending FileFilter

/**
 * Inherited FileFilter class to facilitate reuse when
 * multiple file filter selections are required. For example
 * purposes, I used a static nested class, which is defined
 * as below as a member of our original FileChooserExample
 * class.
 */
static class ExtensionFileFilter 
    extends javax.swing.filechooser.FileFilter {

    private java.util.List<String> extensions;
    private String description;

    public ExtensionFileFilter(String[] exts, String desc) {
        if (exts != null) {
            extensions = new java.util.ArrayList<String>();

            for (String ext : exts) {

                // Clean array of extensions to remove "."
                // and transform to lowercase.
                extensions.add(
                    ext.replace(".", "").trim().toLowerCase()
                );
            }
        } // No else need; null extensions handled below.

        // Using inline if syntax, use input from desc or use
        // a default value.
        // Wrap with an if statement to default as well as
        // avoid NullPointerException when using trim().
        description = (desc != null) ? desc.trim() : "Custom File List";
    }

    // Handles which files are allowed by filter.
    @Override
    public boolean accept(File f) {
    
        // Allow directories to be seen.
        if (f.isDirectory()) return true;

        // exit if no extensions exist.
        if (extensions == null) return false;
		
        // Allows files with extensions specified to be seen.
        for (String ext : extensions) {
            if (f.getName().toLowerCase().endsWith("." + ext))
                return true;
        }

        // Otherwise file is not shown.
        return false;
    }

    // 'Files of Type' description
    @Override
    public String getDescription() {
        return description;
    }
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:

Select allOpen in new window



As you can see, the logic of the FileFilter has been changed to be more dynamic/generic to allow for re-use; however, a lot of the basics hold true.

Using our Custom FileFilter
Now, let's use our named class, taking advantage of the re-usability by adding more than filter with differing number of extensions to the same file chooser:

public static void main(String[] args) {
    // Instantiate the javax.swing.JFileChooser object.
    JFileChooser chooser = new JFileChooser();

    // Add file filter to the chooser object,
    // using custom implementation of abstract
    // javax.swing.filechooser.FileFilter.
    chooser
            .addChoosableFileFilter(new ExtensionFileFilter(
                    new String[] { ".DOC", ".RTF", ".TXT" },
                    "Text Documents (*.DOC|RTF|TXT)"));

    // Add second file filter to the chooser object,
    // using our same implementation class with different
    // constructor parameters.
    chooser
            .addChoosableFileFilter(new ExtensionFileFilter(
                    new String[] { ".CSV" },
                    "Comma Delimited File (*.CSV)"));

    // Verify errant inputs are handled correctly.
    chooser
            .addChoosableFileFilter(new ExtensionFileFilter(
                    null, null));

    // Turn off 'All Files' capability of file chooser,
    // so only our custom filter is used.
    chooser.setAcceptAllFileFilterUsed(false);

    chooser.showSaveDialog(null);
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:

Select allOpen in new window


That's it!

Run this code and you will see how the multiple filters are listed in the "Files of type:" drop-down list and how the files available for selection change as you choose different options from the drop-down.

Checkpoint: modify your program to use your own custom class that extends FileFilter, playing with more complex criteria.  An example code snippet is below for your reference.

Challenge: can you alter your program to add a filter that will only accept PDF files smaller than 500 KB?



4

Wrapping Things Up.


For purposes of our test, save dialog was utilized but file dialogs can be used in other ways as well.

This will present a file dialog for an input file (to be opened):

chooser.showOpenDialog(null);
                                    
1:

Select allOpen in new window



Show a custom file dialog with approval command denoted by second parameter:

chooser.showDialog(null, "Custom Approve Button Text");
                                    
1:

Select allOpen in new window



For all the file dialogs, we used a first parameter of null.  This is the parent component of the file dialog; however, this can be null as shown if you just want to spawn the file dialog from an application that isn't all GUI based like we had above.

Moreover, there are easy ways to set the folder in which the file chooser starts your user when prompted to select file.

For this information and more complex/complete examples of using File Choosers in Java, see the reference link to online tutorial provided by Sun.  You will find some additional references below that may be very useful, so please read and enjoy.




SUMMARY

In conclusion, file choosers are very useful to have in Swing/GUI based applications and even more so with the ability to customize the file filter(s) associated.  The goal of this article was to demonstrate the ways of implementing this, so it is my sincere hope that it has been successful for that purpose and that you have fun coding away your own custom file filtering.

Lastly, special thanks to Venabili who graciously collaborated on the direction and wording of this article!

Happy coding!

Best regards,


Kevin (aka MWVisa1)


Appendix A: Anonymous File Filter Example.
//FileChooserExample.java
package com.experts_exchange;

import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;

/**
 * Example of using file filter(s) with JFileChooser to limit files to specific
 * extension(s).
 * 
 * @author mwvisa1
 */
public class FileChooserExample {

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) {

        // Instantiate the javax.swing.JFileChooser object.
        JFileChooser chooser = new JFileChooser();

        // Add file filter to the chooser object,
        // using anonymous implementation of abstract
        // javax.swing.filechooser.FileFilter.
        chooser.addChoosableFileFilter(new FileFilter() {

            // Handles which files are allowed by filter.
            @Override
            public boolean accept(File f) {
                
                // Allow directories to be seen.
                if (f.isDirectory()) return true;

                // Allows files with .rtf extension to be seen.
                if (f.getName().toLowerCase().endsWith(".rtf"))
                    return true;

                // Otherwise file is not shown.
                return false;
            }

            // 'Files of Type' description
            @Override
            public String getDescription() {
                return "*.RTF";
            }
        });

        // Turn off 'All Files' capability of file chooser,
        // so only our custom filter is used.
        chooser.setAcceptAllFileFilterUsed(false);

        // Where null would be replaced by parent Component.
        chooser.showSaveDialog(null);
    }
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:

Select allOpen in new window




Appendix B: Final Solution.
FileChooserExample.txt
  • 3 KB
  • Final solution's java source.
FileChooserExample.txt

Comments

Add your Comment

Please Sign up or Log in to comment on this article.

Join Experts Exchange Today

Gain Access to all our Tech Resources

Get personalized answers

Ask unlimited questions

Access Proven Solutions

Search 3.2 million solutions

Read In-Depth How-To Guides

1000+ articles, demos, & tips

Watch Step by Step Tutorials

Learn direct from top tech pros

And Much More!

Your complete tech resource

See Plans and Pricing

30-day free trial. Register in 60 seconds.

Loading Advertisement...

Top Java Experts

  1. for_yan

    893,063

    Sage

    1,000 points yesterday

    Profile
    Rank: Genius
  2. CEHJ

    258,666

    Guru

    1,050 points yesterday

    Profile
    Rank: Savant
  3. mccarl

    93,106

    Master

    3,000 points yesterday

    Profile
    Rank: Wizard
  4. girionis

    90,218

    Master

    0 points yesterday

    Profile
    Rank: Genius
  5. dpearson

    86,565

    Master

    498 points yesterday

    Profile
    Rank: Guru
  6. chaituu

    62,368

    Master

    0 points yesterday

    Profile
    Rank: Sage
  7. gudii9

    57,252

    Master

    1,000 points yesterday

    Profile
    Rank: Master
  8. sharonseth

    47,283

    501 points yesterday

    Profile
    Rank: Master
  9. ksivananth

    39,726

    0 points yesterday

    Profile
    Rank: Genius
  10. gordon_vt02

    28,625

    0 points yesterday

    Profile
    Rank: Guru
  11. simonet

    27,400

    0 points yesterday

    Profile
    Rank: Wizard
  12. mrcoffee365

    23,455

    0 points yesterday

    Profile
    Rank: Genius
  13. dravidnsr

    20,609

    501 points yesterday

    Profile
    Rank: Sage
  14. objects

    20,284

    0 points yesterday

    Profile
    Rank: Savant
  15. knsp

    18,558

    0 points yesterday

    Profile
  16. gurvinder372

    18,104

    0 points yesterday

    Profile
    Rank: Genius
  17. santhanasamy

    16,800

    0 points yesterday

    Profile
    Rank: Master
  18. mplungjan

    16,568

    0 points yesterday

    Profile
    Rank: Savant
  19. stmani2005

    15,089

    1,000 points yesterday

    Profile
    Rank: Master
  20. ramazanyich

    14,200

    0 points yesterday

    Profile
    Rank: Sage
  21. CPColin

    13,836

    0 points yesterday

    Profile
    Rank: Guru
  22. arioh

    13,298

    0 points yesterday

    Profile
    Rank: Guru
  23. zzynx

    12,280

    0 points yesterday

    Profile
    Rank: Genius
  24. alexey_gusev

    12,000

    0 points yesterday

    Profile
    Rank: Genius
  25. Gertone

    11,752

    0 points yesterday

    Profile
    Rank: Genius

Hall Of Fame