Java Cookbook, Second Edition

Problem

You need to list the filesystem entries named in a directory.

Solution

Use a java.io.File object's list( ) or listFiles( ) method.

Discussion

The java.io.File class contains several methods for working with directories. For example, to list the filesystem entities named in the current directory, just write:

String[] list = new File(".").list( )

To get an array of already constructed File objects rather than Strings, use:

File[] list = new File(".").listFiles( );

This can become a complete program with as little as the following:

/** Simple directory lister. */ public class Ls { public static void main(String argh_my_aching_fingers[]) { String[] dir = new java.io.File(".").list( ); // Get list of names java.util.Arrays.sort(dir); // Sort it (see Recipe 7.8) for (int i=0; i<dir.length; i++) System.out.println(dir[i]); // Print the list } }

Of course, there's lots of room for elaboration. You could print the names in multiple columns across the page. Or even down the page since you know the number of items in the list before you print. You could omit filenames with leading periods, as does the Unix ls program. Or print the directory names first; I once used a directory lister called lc that did this, and I found it quite useful. By using listFiles( ), which constructs a new File object for each name, you could print the size of each, as per the DOS dir command or the Unix ls -l command (see Recipe 11.1). Or you could figure out whether each is a file, a directory, or neither. Having done that, you could pass each directory to your top-level function, and you'd have directory recursion (the Unix find command, or ls -R, or the DOS DIR /S command).

A more flexible way to list filesystem entries is with list(FilenameFilter ff). FilenameFilter is a tiny little interface with only one method: boolean accept(File inDir, String fileName). Suppose you want a listing of only Java-related files (*.java, *.class, *.jar, etc.). Just write the accept( ) method so that it returns true for these files and false for any others. Here is the Ls class warmed over to use a FilenameFilter instance (my OnlyJava class implements this interface) to restrict the listing:

import java.io.*; /** * FNFilter - Ls directory lister modified to use FilenameFilter */ public class FNFilter { public static void main(String argh_my_aching_fingers[]) { // Generate the selective list, with a one-use File object. String[] dir = new java.io.File(".").list(new OnlyJava( )); java.util.Arrays.sort(dir); // Sort it (Data Structuring chapter)) for (int i=0; i<dir.length; i++) System.out.println(dir[i]); // Print the list } } /** This class implements the FilenameFilter interface. * The Accept method only returns true for .java , .jar and .class files. */ class OnlyJava implements FilenameFilter { public boolean accept(File dir, String s) { if (s.endsWith(".java") || s.endsWith(".class") || s.endsWith(".jar")) return true; // others: projects, ... ? return false; } }

The FilenameFilter need not be a separate class; the online code example FNFilter2 implements the interface directly in the main class, resulting in a slightly shorter file. In a full-scale application, the list of files returned by the FilenameFilter would be chosen dynamically, possibly automatically, based on what you were working on. As we'll see in Recipe 14.11, the file chooser dialogs implement a superset of this functionality, allowing the user to select interactively from one of several sets of files to be listed. This is a great convenience in finding files, just as it is here in reducing the number of files that must be examined.

Категории