The File class | CodeGuru

The File class

Bruce Eckel’s Thinking in Java Contents | Prev | Next The File class has a deceiving name – you might think it refers to a file, but it doesn’t. It can represent either the name of a particular file or the names of a set of files in a directory. If it’s a set of […]

Written By
CodeGuru Staff
CodeGuru Staff
Mar 1, 2001
6 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

The


File
class
has a deceiving name – you might think it refers to a file, but it
doesn’t. It can represent either the
name
of a particular file or the
names
of a set of files in a directory. If it’s a set of files, you can ask for
the set with the
list( )
method, and this returns an array of
String.
It makes sense to return an array rather than one of the flexible collection
classes because the number of elements is fixed, and if you want a different
directory listing you just create a different
File
object. In fact, “FilePath” would have been a better name. This
section shows a complete example of the use of this class, including the
associated
FilenameFilter
interface.

A
directory lister

Suppose


you’d like to see a directory listing. The


File

object can be listed in two ways. If you call


list( )

with no arguments, you’ll get the full list that the


File

object contains. However, if you want a restricted list, for example, all of


the files with an extension of


.java

,


then you use a “directory filter,” which is a class that tells how


to select the


File

objects for display.

Here’s


the code for the example: (See page


97

if you have trouble executing this program.)

//: DirList.java
// Displays directory listing
package c10;
import java.io.*;
 
public class DirList {
  public static void main(String[] args) {
    try {
      File path = new File(".");
      String[] list;
      if(args.length == 0)
        list = path.list();
      else
        list = path.list(new DirFilter(args[0]));
      for(int i = 0; i < list.length; i++)
        System.out.println(list[i]);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}
 
class DirFilter implements FilenameFilter {
  String afn;
  DirFilter(String afn) { this.afn = afn; }
  public boolean accept(File dir, String name) {
    // Strip path information:
    String f = new File(name).getName();
    return f.indexOf(afn) != -1;
  }
} ///:~ 

The


DirFilter

class “implements” the


interface
FilenameFilter

.


(Interfaces were covered in Chapter 7.) It’s useful to see how simple the


FilenameFilter
interface

is:

public interface FilenameFilter {
  boolean accept(File dir, String name);
}

It


says that all that this type of object does is provide a method called


accept( )

.


The whole reason behind the creation of this class is to provide the


accept( )

method to the


list( )

method so that


list( )

can


call
back

accept( )

to determine which file names should be included in the list. Thus, this


technique is often referred to as a

callback
or sometimes a
functor
(that is,
DirFilter
is a functor because its only job is to hold a method). Because
list( )
takes a
FilenameFilter
object as its argument, it means that you can pass an object of any class that
implements
FilenameFilter
to choose (even at run-time) how the
list( )
method will behave. The purpose of a callback is to provide flexibility in the
behavior of code.
DirFilter

shows that just because an


interface

contains only a set of methods, you’re not restricted to writing only


those methods. (You must at least provide definitions for all the methods in an


interface, however.) In this case, the


DirFilter

constructor is also created.

The


accept( )

method must accept a


File

object representing the directory that a particular file is found in, and a


String

containing the name of that file. You might choose to use or ignore either of


these arguments, but you will probably at least use the file name. Remember


that the


list( )

method is calling


accept( )

for each of the file names in the directory object to see which one should be


included – this is indicated by the


boolean

result returned by


accept( )

.

To


make sure that what you’re working with is only the name and contains no


path information, all you have to do is take the


String

object and create a


File

object out of it, then call


getName( )

which strips away all the path information (in a platform-independent way). Then


accept( )

uses the

String
class
indexOf( )
method to see if the search string
afn
appears anywhere in the name of the file. If
afn
is found within the string, the return value is the starting index of
afn,
but if it’s not found the return value is -1. Keep in mind that this is a
simple string search and does not have regular expression
“wildcard” matching such as “fo?.b?r*” which is much
more difficult to implement.

The


list( )

method returns an array. You can query this array for its length and then move


through it selecting the array elements. This ability to easily pass an array


in and out of a method is a tremendous improvement over the behavior of C and


C++.


Anonymous
inner classes

This


example is ideal for rewriting using an

anonymous
inner class (described in Chapter 7). As a first cut, a method
filter( )
is
created that returns a handle to a
FilenameFilter:
//: DirList2.java
// Uses Java 1.1 anonymous inner classes
import java.io.*;
 
public class DirList2 {
  public static FilenameFilter
  filter(final String afn) {
    // Creation of anonymous inner class:
    return new FilenameFilter() {
      String fn = afn;
      public boolean accept(File dir, String n) {
        // Strip path information:
        String f = new File(n).getName();
        return f.indexOf(fn) != -1;
      }
    }; // End of anonymous inner class
  }
  public static void main(String[] args) {
    try {
      File path = new File(".");
      String[] list;
      if(args.length == 0)
        list = path.list();
      else
        list = path.list(filter(args[0]));
      for(int i = 0; i < list.length; i++)
        System.out.println(list[i]);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
} ///:~ 

Note


that the argument to


filter( )

must be

final.
This is required by the anonymous inner class so that it can use an object from
outside its scope.

This


design is an improvement because the


FilenameFilter

class is now tightly bound to


DirList2

.


However, you can take this approach one step further and define the anonymous


inner class as an argument to


list( )

,


in which case it’s even smaller:

//: DirList3.java
// Building the anonymous inner class "in-place"
import java.io.*;
 
public class DirList3 {
  public static void main(final String[] args) {
    try {
      File path = new File(".");
      String[] list;
      if(args.length == 0)
        list = path.list();
      else
        list = path.list(
          new FilenameFilter() {
            public boolean
            accept(File dir, String n) {
              String f = new File(n).getName();
              return f.indexOf(args[0]) != -1;
            }
          });
      for(int i = 0; i < list.length; i++)
        System.out.println(list[i]);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
} ///:~ 

The


argument to


main( )

is now


final

,


since the anonymous inner class uses


args[0]

directly.

This


shows you how anonymous inner classes allow the creation of quick-and-dirty


classes to solve problems. Since everything in Java revolves around classes,


this can be a useful coding technique. One benefit is that it keeps the code


that solves a particular problem isolated together in one spot. On the other


hand, it is not always as easy to read, so you must use it judiciously.


A
sorted directory listing

Ah,


you say that you want the file names


sorted

?


Since there’s no support for sorting in Java 1.0 or Java 1.1


(although sorting
is
included in Java 1.2
),
it will have to be added into the program directly using the
SortVector
created
in Chapter 8:
//: SortedDirList.java
// Displays sorted directory listing
import java.io.*;
import c08.*;
 
public class SortedDirList {
  private File path;
  private String[] list;
  public SortedDirList(final String afn) {
    path = new File(".");
    if(afn == null)
      list = path.list();
    else
      list = path.list(
          new FilenameFilter() {
            public boolean
            accept(File dir, String n) {
              String f = new File(n).getName();
              return f.indexOf(afn) != -1;
            }
          });
    sort();
  }
  void print() {
    for(int i = 0; i < list.length; i++)
      System.out.println(list[i]);
  }
  private void sort() {
    StrSortVector sv = new StrSortVector();
    for(int i = 0; i < list.length; i++)
      sv.addElement(list[i]);
    // The first time an element is pulled from
    // the StrSortVector the list is sorted:
    for(int i = 0; i < list.length; i++)
      list[i] = sv.elementAt(i);
  }
  // Test it:
  public static void main(String[] args) {
    SortedDirList sd;
    if(args.length == 0)
      sd = new SortedDirList(null);
    else
      sd = new SortedDirList(args[0]);
    sd.print();
  }
} ///:~ 

A


few other improvements have been made. Instead of creating


path

and


list

as local variables to


main( )

,


they are members of the class so their values can be accessible for the


lifetime of the object. In fact,


main( )

is now just a way to test the class. You can see that the constructor of the


class automatically sorts the list once that list has been created.

The


sort is case-insensitive so you don’t end up with a list of all the words


starting with capital letters, followed by the rest of the words starting with


all the lowercase letters. However, you’ll notice that within a group of


file names that begin with the same letter the capitalized words are listed


first, which is still not quite the desired behavior for the sort. This problem


will be fixed in Java 1.2

.

Checking
for and creating directories

The


File

class is more than just a representation for an existing directory path, file,


or group of files. You can also use a


File

object to create a new

directory
or an entire directory path if it doesn’t exist. You can also look at the
characteristics
of files (size, last modification date, read/write), see whether a
File
object represents a file or a directory, and delete a file. This program shows
the remaining methods available with the
File
class:
//: MakeDirectories.java
// Demonstrates the use of the File class to
// create directories and manipulate files.
import java.io.*;
 
public class MakeDirectories {
  private final static String usage =
    "Usage:MakeDirectories path1 ...n" +
    "Creates each pathn" +
    "Usage:MakeDirectories -d path1 ...n" +
    "Deletes each pathn" +
    "Usage:MakeDirectories -r path1 path2n" +
    "Renames from path1 to path2n";
  private static void usage() {
    System.err.println(usage);
    System.exit(1);
  }
  private static void fileData(File f) {
    System.out.println(
      "Absolute path: " + f.getAbsolutePath() +
      "n Can read: " + f.canRead() +
      "n Can write: " + f.canWrite() +
      "n getName: " + f.getName() +
      "n getParent: " + f.getParent() +
      "n getPath: " + f.getPath() +
      "n length: " + f.length() +
      "n lastModified: " + f.lastModified());
    if(f.isFile())
      System.out.println("it's a file");
    else if(f.isDirectory())
      System.out.println("it's a directory");
  }
  public static void main(String[] args) {
    if(args.length < 1) usage();
    if(args[0].equals("-r")) {
      if(args.length != 3) usage();
      File
        old = new File(args[1]),
        rname = new File(args[2]);
      old.renameTo(rname);
      fileData(old);
      fileData(rname);
      return; // Exit main
    }
    int count = 0;
    boolean del = false;
    if(args[0].equals("-d")) {
      count++;
      del = true;
    }
    for( ; count < args.length; count++) {
      File f = new File(args[count]);
      if(f.exists()) {
        System.out.println(f + " exists");
        if(del) {
          System.out.println("deleting..." + f);
          f.delete();
        }
      }
      else { // Doesn't exist
        if(!del) {
          f.mkdirs();
          System.out.println("created " + f);
        }
      }
      fileData(f);
    }
  }
} ///:~ 

In


fileData( )

you can see the various file investigation methods put to use to display


information about the file or directory path.

The


first method that’s exercised by


main( )

is

renameTo( ),
which allows you to rename (or move) a file to an entirely new path represented
by the argument, which is another
File
object. This also works with directories of any length.

If


you experiment with the above program, you’ll find that you can make a


directory path of any complexity because

mkdirs( )
will do all the work for you. In Java 1.0
,
the
-d
flag reports that the directory is deleted but it’s still there; in Java
1.1

the directory is actually deleted.
Contents

|

Prev

|

Next
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.