Main Page

Previous Next

Working with File Objects

It is easy to forget that a File object doesn't actually represent a file. You need to keep reminding yourself that a File object encapsulates a pathname or reference to what may or may not be a physical file or directory on your hard disk, not the physical file or directory itself. The fact that you create a File object does not determine that a file or directory actually exists. This is not as strange as it might seem at first sight. After all, you will often be defining a File object that encapsulates a path to a new file or directory that you intend to create.

As we will see, a File object serves two purposes:

  • It enables you to check the pathname that it encapsulates against the physical file system and see whether it corresponds to a real file or directory.

  • You can use it to create file stream objects.

The File class provides several methods for you to test the path that a File object encapsulates in various ways, as well as the physical file or directory it may represent. You can determine whether or not an object does represent a path to an existing file or directory, for example. If a File object does correspond to a real file, you have methods available that you can use to modify the file in a number of ways.

Creating File Objects

You have a choice of four constructors for creating File objects. The simplest accepts a String object as an argument that specifies a path for a file or a directory. For example, you could write the statement:

File myDir = new File("C:/j2sdk1.4.0/src/java/io");

This creates a File object encapsulating the path C:/j2sdk1.4.0/src/java/io. On my system, this happens to be the path to the directory, io, containing the classes in the java.io package. On the various flavors of the Microsoft Windows operating system, you can also use an escaped back slash separator, \\, when you define a path, instead of /, if you wish, but paths do tend to look rather busy if you do. For instance:

File myDir = new File("C:\\jdk1.4\\src\\java\\io");

It also requires more typing.

Note that the File class constructor here does not check the string that you pass as the argument in any way, so there is no guarantee that a File object encapsulates a valid representation of a path on your system at all. For instance, this will compile and execute perfectly well:

File junk = new File("dwe\n:;?cc/.*\naa£%)(");  // Not a valid path! 

The argument to the constructor here does not define a valid file or directory path – at least not under any operating system that I am familiar with – but that statement compiles and executes. We can therefore deduce that you can pass any string as an argument to the File class constructor. It is up to you to ensure that it is valid for your system.

To specify a pathname to a file, you just need to make sure that the string that you pass as an argument to the constructor does refer to a file, and not a directory. For example, the statement:

File myFile = new File("C:/j2sdk1.4.0/src/java/io/File.java");

sets the object, myFile, to correspond to the source file for the definition of the class, File.

An important and easily overlooked characteristic of File objects is that they are immutable. Once you have created a File object you cannot change the path it encapsulates. We will see later that you can change the name of the physical file it references by using the rename() method belonging to the File object, but this will not change the File object itself. The File object will still encapsulate the original path so that once the file name has been changed the path encapsulated by the File object will no longer refer to an existing file. This can be confusing if you don't realize this is the case. Using this File object to test whether the file exists, for instance, will return false.

You can also create a File object that represents a pathname for a file by using a constructor that allows you to specify the directory that contains the file and the file name separately. The directory that contains the file is usually referred to as the parent directory. There are two constructors that allow you to do this, providing you with a choice as to how you specify the parent directory. In one, the first argument is a reference to a File object that encapsulates the path for the directory containing the file. In the other, the first argument specifies the parent directory path as a String object. The second argument in both cases is a String object identifying the file name.

For example, on my system, I can identify the Java source file for the File class with the statements:

File myDir = new File("C:/j2sdk1.4.0/src/java/io");  // Parent directory
File myFile = new File(myDir, "File.java");         // The path to the file

The first statement creates a File object that refers to the directory for the package io, and the second statement creates a File object that corresponds to the file, File.java, in that directory.

We could use the second of the two constructors to achieve the same result as the previous two statements:

File myFile = new File("C:/j2sdk1.4.0/src/java/io", "File.java");

Using a File object to specify the directory is much more useful than using a string directly. For instance, you can verify that the directory does really exist before attempting to access the file or files that you are interested in. You can also create the directory if necessary, as we shall see.

The fourth constructor allows you to define a File object from an object of type URI that encapsulates a Uniform Resource Identifier, commonly known as a URI. As you are undoubtedly aware, a URI is used to reference a resource on the World Wide Web and the most common form of URI is a URL – a Uniform Resource Locator. A URL usually consists of a protocol specification such as HTTP, a host machine identification such as p2p.wrox.com, plus a name that refers to a particular resource on that machine such as java, so for instance, http://p2p.wrox.com/java is a URL that references a page on a Wrox Press server that contains a list of forums related to Java books that are published by Wrox Press.

The URI class provides several constructors for creating URI objects but getting into the detail of these is too much of a diversion from our present topic – dealing with local files. However, the simplest constructor just accepts a reference to a String object and we could use this to create a File object like this:

File remoteFile = new File(new URL(http://p2p.wrox.com/java));

References to physical files inevitably tend to be system-dependent since each operating system will have its own conventions for specifying a path to a file. If you refer to a particular file in the directory C:\My Java Stuff under Windows, this path will not be recognized under Unix. However, Java provides capabilities that enable you to avoid system dependencies when you specify file paths, at least to some extent, so let's look at those in more detail.

Portable Path Considerations

The File class contains a static member, separator, of type String that defines the separator that is used between names in a path by your operating system. Under Unix, this will be defined as "/" and under MS Windows it will be "\\". As we have seen, when you are specifying a path by a string under Windows, you can use either of these characters as a path name separator. Another static field, separatorChar, defines the same separator character as type char for convenience, so you can use whichever suits you. The File class also defines the system default character for separating one path from another as the static member pathSeparator, which is of type String, or pathSeparatorChar, which is of type char. The path separator is a semicolon under MS Windows and a colon under Unix.

Of course, the specific makeup of a path is system-dependent but we could have used the separator field in the File class to specify the path for myFile in a slightly more system-independent way, like this:

File myFile = new File("C:" + File.separator + "jdk1.4" + File.separator +
                       "src" + File.separator + "java" + File.separator +
                       "io", "File.java");

This defines the same path as the previous statement but without using an explicit separator character between the names in the path. While we have specified the pathname separator character in a portable fashion, the argument to the File class constructor is still specific to Windows because we have specified the drive letter as part of the path. To remove the Windows-specific element in the file path we would have to omit the drive letter from the path specification. In this case we would have a relative path specification.

Absolute and Relative Paths

In general, the pathname that you use to create a File object has two parts: an optional prefix, followed by a series of names separated by the system default separator character for pathnames. Under MS Windows the prefix for a path on a local drive will be a string defining the drive, such as "C:\\" or "C:/". Under Unix the prefix will be a forward slash, "/". A path that includes a prefix is an absolute path and since it includes a prefix it is not system-independent. A path without a prefix is a relative path and as long as it consists of one or more names separated by characters specified as File.separator or File.separatorChar it should be portable across different systems. The last name in a path can be a directory name or a filename. All other names must be directory names. If you use anything other than this – if you use any system-specific conventions to specify the path for instance – naturally you no longer have a system-independent path specification.

The pathnames we have used in the preceding code fragments have all been absolute paths, since we included the drive letter in the path for Windows, or a forward slash to identify the Unix root directory. If you omit this, you have a relative path, and the pathname string will be interpreted as a path relative to the current directory. This implies that you can reference a file that is in the same directory as your program by just the file name.

For example:

File myFile = new File("output.txt");

This statement creates a File object encapsulating the path to a file with the name "output.txt" in the current directory, whatever that happens to be. It corresponds to the directory that was current when program execution was initiated. We will see in a moment how we can obtain the absolute path from a File object, regardless of how the File object was created.

You could also refer to a file in a subdirectory of the current directory using a relative path:

File myFile = new File("dir" + separator + "output.txt");

Thus we can use a relative path specification to reference files in the current directory, or in any subdirectory of the current directory, and since a relative path does not involve the system-dependent prefix, this will work across different operating systems.

As we have seen, an absolute path in a Windows environment can have a prefix that is an explicit drive specification but you can also use the UNC (Universal Naming Convention) representation of a path that provides a machine-independent way of identifying paths to shared resources on a network. The UNC representation of a path always begins with two backslashes, followed by the machine name, followed by the share name. In general, a UNC path will be of the form:

\\servername\directory_path\filename

On a computer with the name myPC, with a shared directory shared, you could create a File object as follows:

File myFile = new File("\\\\myPC\\shared\\jdk1.4\\src\\java\\io",
                         "File.java");

If you are keen to practice your typing skills, you could also write this as:

File myFile = new File(File.separator + File.separator + "myPC" +
                       File.separator + "shared" + File.separator +
                       "jdk1.4" + File.separator + "src" + File.separator + 
                       "java" + File.separator + "io", "File.java");

If you want to create a File object that refers to the root directory under Unix, you just use "/" as the path.

Accessing System Properties

While you can specify a relative path to a file is that not system-dependent, there may be circumstances where you want to specify a path that is independent of the current environment, but where the current directory, or even a subdirectory of the current directory, is not a convenient place to store a data file. In this case accessing one of the system properties can help. A system property specifies values for parameters related to the system environment in which your program is executing. Each system property is identified by a unique name, and has a value associated with the name that is defined as a string. There is a set of standard system properties that will always be available and you can access the values of any of these by passing the name of the property that you are interested in to the static getProperty() method that is defined in the System class.

For instance, the directory that is the default base for relative paths is defined by the property that has the name "user.dir", so we can access the path to this directory with the statement:

String currentDir = System.getProperty("user.dir");

We could then use this to specify explicitly where the file with the name "output.txt" is located:

File dataFile = new File(currentDir, "output.txt");

Of course, this is equivalent to just specifying the file name as the relative path, so we have not achieved anything new. However, there is another system property with the name "user.home" that has a value that defines a path to the user's home directory. We could therefore specify that the "output.txt" file is to be in this directory like this:

File dataFile = new File(System.getProperty("user.home"), "output.txt");

The location of the user's home directory is system-dependent, but wherever it is you can access it in this way without building system dependencies into your code.

Naturally, you could specify the second argument to the constructor here to include directories that are to be subdirectories of the home directory. For instance:

File dataFile = new File(System.getProperty("user.home"),
                         "dir" + File.separator + "output.txt");

On my system this defines the path:

C:\Documents and Settings\Ivor Horton\dir\output.txt

If you want to plug this code fragment into a main() method and see what path the resultant File object encapsulates, the following statement will output the absolute path for you.

System.out.println(dataFile.getAbsolutePath());

This uses the getAbsolutePath() method for the File object to obtain the absolute path as a reference to a String object. We will come back to this method in a moment.

If you would like to see what the full set of standard system properties are, you will find the complete list in the SDK documentation for the getProperties() method in the System class.

Testing and Checking File Objects

The File class provides more than 30 methods that you can apply to File objects, so we will look at the ones that will be most useful, grouped by the sorts of things that they do.

First of all, you can get information about a File object itself by using the following methods:

Method

Description

getName ()

Returns a String object containing the name of the file without the path – in other words the last name in the path stored in the object. For a File object representing a directory, just the directory name is returned.

getPath()

Returns a String object containing the path for the File object – including the file or directory name.

isAbsolute()

Returns true if the File object refers to an absolute path name, and false otherwise. Under Windows 95, 98, or NT, an absolute path name begins with either a drive letter followed by a colon then a backslash or a double backslash. Under Unix, an absolute path is specified from the root directory down.

getParent()

Returns a String object containing the name of the parent directory of the file or directory represented by the current File object. This will be the original path without the last name. The method returns null if there is no parent specified. This will be the case if the File object was created for a file in the current directory by just using a file name.

toString()

Returns a String representation of the current File object and is called automatically when a File object is concatenated with a String object. We have used this method implicitly in output statements. The string that is returned is the same as that returned by the getPath() method.

hashCode()

Returns a hash code value for the current File object. We will see more about what hash codes are used for in Chapter 10.

equals()

You use this method for comparing two File objects for equality. If the File object passed as an argument to the method has the same path as the current object, the method returns true. Otherwise, it returns false.

All of the above involve just the information encapsulated by the File object. The file or directory itself is not queried and may or may not exist. The methods in the File class that enable you to check out a file or directory are much more interesting and useful, so let's go directly to those next.

Querying Files and Directories

The following basic set of methods are provided for examining the file or directory that is identified by a File object:

Method

Description

exists()

Returns true if the file or directory referred to by the File object exists and false otherwise.

isDirectory()

Returns true if the File object refers to an existing directory and false otherwise.

isFile()

Returns true if the File object refers to an existing file and false otherwise.

isHidden()

Returns true if the File object refers to a file that is hidden and false otherwise. How a file is hidden is system-dependent. Under Unix a hidden file has a name that begins with a dot. Under Windows a file is hidden if it is marked as such within the file system.

canRead()

Returns true if you are permitted to read the file referred to by the File object, and false otherwise. This method can throw a SecurityException if read access to the file is not permitted.

canWrite()

Returns true if you are permitted to write to the file referred to by the File object and false otherwise. This method may also throw a SecurityException if you are not allowed to write to the file.

getAbsolutePath()

Returns the absolute path for the directory or file referenced by the current File object. If the object contains an absolute path, then the string returned by getPath() is returned. Otherwise, under MS Windows the path is resolved against the current directory for the drive identified by the pathname, or against the current user directory if no drive letter appears in the pathname, and against the current user directory under UNIX.

getAbsoluteFile()

Returns a File object containing the absolute path for the directory or file referenced by the current File object.

When you are working with a File object, you may not know whether it contains an absolute or a relative path. However, you may well want to get hold of its parent directory – to create another file for instance. For a File object created from a relative path, the getParent() method will return null. In this case you can use the getAbsolutePath()method to obtain the absolute path, or the getAbsoluteFile() method to ensure that you have a File object for which the getParent() method will return a string representing the complete path for the parent directory. For instance:

File dataFile = new File("output.txt");

Calling getParent() for dataFile here will return null. However, we can create a new File object encapsulating the absolute path:

dataFile = dataFile.getAbsoluteFile();

Now dataFile refers to a new object that encapsulates the absolute path to "output.txt", so calling getParent() will return the path to the parent directory – which will correspond to the value of the user.dir system property in this case.

Important 

Note that all operations involving the access of files on the local machine can throw a SecurityException if access is not authorized – in an applet for instance. This is the case with all of the methods here. However, for a SecurityException to be thrown, a security manager must exist on the local machine, but by default a Java application has no security manager. An applet, on the other hand, always has a security manager, by default. A detailed discussion of Java security is beyond the scope of this book. A comprehensive discussion of this topic is provided by the book "Professional Java Security" by Jess Garms and Daniel Somerfield, published by Wrox Press, ISBN 1861004257.

To see how some of these methods go together, we can try a simple example.

Try It Out – Testing for a File

Try the following source code. Don't forget the import statement for the java.io package, since the example won't compile without it. The source code is in a zip called src.jar, and can be found in the home directory for the JDK. If you haven't installed the Java source code on your system, you could try the example with the file that contains the source code for the example itself – TryFile.java:

Important 

In all the examples in this chapter, you may need to specify substitute paths to suit your environment.

import java.io.File;

public class TryFile {
  public static void main(String[] args) {

    // Create an object that is a directory
    File myDir = new File("C:/j2sdk1.4.0/src/java/io");
    System.out.println(myDir + (myDir.isDirectory() ? " is" : " is not")
                       + " a directory.");

    // Create an object that is a file
    File myFile = new File(myDir, "File.java");
    System.out.println(myFile + (myFile.exists() ? " does" : " does not")
                       + " exist");
    System.out.println(myFile + (myFile.isFile() ? " is" : " is not")
                       + " a file.");
    System.out.println(myFile + (myFile.isHidden() ? " is" : " is not")
                       + " hidden");
    System.out.println("You can" + (myFile.canRead() ? " " : "not ")
                       + "read " + myFile);
    System.out.println("You can" + (myFile.canWrite() ? " " : "not ")
                       + "write " + myFile);
    return;
  }
}

On my machine, the above example produces the output:

C:\j2sdk1.4.0\src\java\io is a directory.
C:\j2sdk1.4.0\src\java\io\File.java does exist
C:\j2sdk1.4.0\src\java\io\File.java is a file.
C:\j2sdk1.4.0\src\java\io\File.java is not hidden
You can read C:\j2sdk1.4.0\src\java\io\File.java
You can write C:\j2sdk1.4.0\src\java\io\File.java

How It Works

This program first creates an object corresponding to the directory containing the java.io package. You will need to check the path to this directory on your own system and insert that as the argument to the constructor of the File object. The output statement then uses the conditional operator ?: in conjunction with the isDirectory() method to display a message. If isDirectory()returns true, then " is" is selected. Otherwise, " is not" is selected. The program then creates another File object corresponding to the file File.java and displays further information about the file using the same sort of mechanism. Finally, the program uses the canRead() and canWrite() methods to determine whether read and write access to the file is permitted.

If you are using MS Windows, you might like to try out the separator \\ with this example and see if it makes a difference.

The following methods provide further information about the file or directory, if it exists:

Method

Description

list()

If the current File object represents a directory, a String array is returned containing the names of the members of the directory. If the directory is empty, the array will be empty. If the current file object is a file, null is returned. The method will throw an exception of type SecurityException if access to the directory is not authorized.

listFiles()

If the object for which this method is called is a directory, it returns an array of File objects corresponding to the files and directories in that directory. If the directory is empty, then the array that is returned will be empty. The method will return null if the object is not a directory, or if an I/O error occurs. The method will throw an exception of type SecurityException if access to the directory is not authorized.

length()

Returns a value of type long that is the length in bytes of the file represented by the current File object. If the pathname for the current object references a file that does not exist then the method will return zero. If the pathname refers to a directory, then the value returned is undefined.

lastModified()

Returns a value of type long that represents the time that the directory or file represented by the current File object was last modified. This time is the number of milliseconds since midnight on 1st January 1970 GMT. It returns zero if the file does not exist.

There is also a static method defined in the File class, listRoots(), which returns an array of File objects. Each element in the array that is returned corresponds to a root directory in the current file system. The path to every file in the system will begin with one or other of these roots. In the case of a Unix system for instance, the array returned will contain just one element corresponding to the single root on a Unix system, /. Under MS Windows, the array will contain an element for each logical drive that you have, including floppy drives, CD drives, and DVD drives. The following statements will list all the root directories on your system:

File[] roots = File.listRoots();
for(int i = 0 ; i<roots.length ; i++)
  System.out.println("Root directory " + i + ": " + roots[i]);

The for loop lists the elements of the array returned by the listRoots() method.

With a variation on the last example, we can try out some of these methods.

Try It Out – Getting More Information

We can arrange to list all the files in a directory and record when they were last modified with the following program:

import java.io.File;
import java.util.Date;   // For the Date class

public class TryFile2 {
  public static void main(String[] args) {

    // Create an object that is a directory
    File myDir = new File("C:/j2sdk1.4.0/src/java/io");
    System.out.println(myDir.getAbsolutePath() 
                       + (myDir.isDirectory() ? " is " : " is not ")
                       + "a directory");
    System.out.println("The parent of " + myDir.getName() + " is "
                       + myDir.getParent());

    // Get the contents of the directory
    File[] contents = myDir.listFiles();

    // List the contents of the directory
    if (contents != null) {
      System.out.println("\nThe " + contents.length
                         + " items in the directory " + myDir.getName()
                         + " are:");
      for (int i = 0; i < contents.length; i++) {
        System.out
          .println(contents[i] + " is a " 
                   + (contents[i].isDirectory() ? "directory" : "file")
                   + " last modified " 
                   + new Date(contents[i].lastModified()));
      }
    } else {
      System.out.println(myDir.getName() + " is not a directory");
    }

    System.exit(0);
  }
}

Again, you need to use a path that is appropriate for your system. You should not have any difficulty seeing how this works. The first part of the program creates a File object representing the same directory as in the previous example. The second part itemizes all the files and subdirectories in the directory. The output will look something like this,

C:\j2sdk1.4.0\src\java\io is a directory
The parent of io is C:\j2sdk1.4.0\src\java

The 78 items in the directory io are:
C:\j2sdk1.4.0\src\java\io\Bits.java is a file last modified Sat Oct 20 01:13:38 BST 2001
C:\j2sdk1.4.0\src\java\io\BufferedInputStream.java is a file last modified Sat Oct 20 01:13:38 BST 2001
C:\j2sdk1.4.0\src\java\io\BufferedOutputStream.java is a file last modified Sat Oct 20 01:13:38 BST 2001
   .
   .
   .

and so on.

How It Works

You can see that the getName()method just returns the file name or the directory name, depending on what the File object represents.

The listFiles()method returns a File array, with each element of the array representing a member of the directory, which could be a subdirectory or a file. We store the reference to the array returned by the method in our array variable contents. After outputting a heading, we check that the array is not null. We then list the contents of the directory in the for loop. We use the isDirectory() method to determine whether each item is a file or a directory, and create the output accordingly. We could just as easily have used the isFile()method here. The lastModified() method returns a long value that represents the time when the file was last modified in milliseconds since midnight on January 1st 1970. To get this to a more readable form, we use the value to create a Date object, and the toString() method for the class returns what you see in the output. The Date class is defined in the java.util package. (See Chapter 13.) We have imported this into the program file but we could just as well use the fully qualified class name, java.util.Date, instead. If the contents array is null, we just output a message. You could easily add code to output the length of each file here, if you want.

Note that there is a standard system property with the name java.home that identifies the directory that is the root directory of the Java runtime environment. If you have installed the SDK (rather than just a JRE), this will be the jre subdirectory to the SDK subdirectory, which on my system is C:/SDK1.4. In this case the value of java.home will be "C:/sdk1.4/jre". You could therefore use this to refer to the file in the previous example in a system-independent way. If you create a File object from the value of the java.home property, calling its getParent() method will return the parent directory as a String object. This will be the SDK home directory so you could use this as the base directory to access the source files for the class libraries, like this:

    File myDir = new File(new File(System.getProperty("java.home")).getParent(),
                          "src" + File.separator+"java" + File.separator+"io");

As long as the JRE in effect is the one installed as part of the SDK, we have a system-independent way of accessing the source files for the library classes.

Filtering a File List

The list()and listFiles()methods are overloaded with versions that accept an argument used to filter a file list. This enables you to get a list of those files with a given extension, or with names that start with a particular sequence of characters. For example, you could ask for all files starting with the letter 'T', which might return the two files we created above: "TryFile.java" and "TryFile2.java". The argument that you pass to the list() method must be a variable of type FilenameFilter whereas the listFiles() method is overloaded with versions to accept arguments of type FilenameFilter or FileFilter. Both FilenameFilter and FileFilter are interfaces that contain the abstract method accept(). The FilenameFilter interface is defined in the java.io package as:

public interface FilenameFilter {
  public abstract boolean accept(File directory, String filename);
}

The FileFilter interface, also defined in java.io, is very similar:

public interface FileFilter {
  public abstract boolean accept(File pathname);
}

The only distinction between these two is the parameter list for the method in the interfaces. The accept() method in the FilenameFilter class has two parameters for you to specify the directory plus the file name to identify a particular file, so this is clearly aimed at testing whether a given file should be included in a list of files. The accept() method for the FileFilter interface has just a single parameter of type File, this is used to filter files and directories.

The filtering of the list is achieved by the list() or listFiles() method by calling the method accept() for every item in the raw list. If the method returns true, the item stays in the list, and if it returns false, the item is not included. Obviously, these interfaces act as a vehicle to allow the mechanism to work, so you need to define your own class that implements the appropriate interface. If you are using the list() method, your class must implement the FilenameFilter interface. If you are using the listFiles() method, you can implement either interface. How you actually filter the filenames is entirely up to you. You can arrange to do whatever you like within the class that you define. We can see how this works by extending the previous example a little further.

Try It Out – Using the FilenameFilter Interface

We can define a class to specify a file filter as:

import java.io.File;
import java.io.FilenameFilter;
import java.util.Date;        // For the Date class

public class FileListFilter implements FilenameFilter {
  private String name;        // File name filter
  private String extension;   // File extension filter

  // Constructor
  public FileListFilter(String name, String extension) {
    this.name = name;
    this.extension = extension;
  }

  public boolean accept(File directory, String filename) {
    boolean fileOK = true;

    // If there is a name filter specified, check the file name
    if (name != null)
      fileOK &= filename.startsWith(name);

    // If there is an extension filter, check the file extension
    if (extension != null)
      fileOK &= filename.endsWith('.' + extension);

    return fileOK;
  }
}

This uses the methods startsWith() and endsWith(), which are defined in the String class that we discussed in Chapter 4. Save this source in the same directory as the previous example, as FileListFilter.java.

Now we need to modify our TryFile2.java code as follows:

import java.io.File;
import java.io.FilenameFilter;
import java.util.Date;   // For the Date class

public class TryFile3 {
  public static void main(String[] args) {

    // Create an object that is a directory
    File myDir = new File("C:/j2sdk1.4.0/src/java/io");
    System.out.println(myDir.getAbsolutePath() 
                       + (myDir.isDirectory() ? " is " : " is not ")
                       + "a directory");
    System.out.println("The parent of " + myDir.getName() + " is "
                       + myDir.getParent());

    // Define a filter for java source files beginning with F
    FilenameFilter select = new FileListFilter("F", "java");

    // Get the contents of the directory
    File[] contents = myDir.listFiles(select);

    // List the contents
    if (contents != null) {
      System.out.println("\nThe " + contents.length
                         + " matching items in the directory, "
                         + myDir.getName() + ", are:");
      for (int i = 0; i < contents.length; i++) {
        System.out
          .println(contents[i] + " is a "
                   + (contents[i].isDirectory() ? "directory" : "file")
                   + " last modified " 
                   + new Date(contents[i].lastModified()));
      } 
    } else {
      System.out.println(myDir.getName() + " is not a directory");
    } 

    return;
  }
}

It is best to continue with our numbering convention and call the above script TryFile3.java. When you run this code, you should get something like the following:

C:\j2sdk1.4.0\src\java\io is a directory
The parent of io is C:\j2sdk1.4.0\src\java

The 15 matching items in the directory, io, are:
C:\j2sdk1.4.0\src\java\io\File.java is a file last modified Sat Oct 20 01:13:38 BST 2001
C:\j2sdk1.4.0\src\java\io\FileDescriptor.java is a file last modified Sat Oct 20 01:13:38 BST 2001
C:\j2sdk1.4.0\src\java\io\FileFilter.java is a file last modified Sat Oct 20 01:13:38 BST 2001
C:\j2sdk1.4.0\src\java\io\FileInputStream.java is a file last modified Sat Oct 20 01:13:38 BST 2001
   .
   .
   .

and so on.

How It Works

Our FileListFilter class has two instance variables – name and extension. The name variable stores the file name prefix, and extension selects file types to be included in a list. The constructor sets these variables, and the value of either can be omitted when the constructor is called, by specifying the appropriate argument as null. If you want a really fancy filter, you can have just one argument to the constructor and specify the filter as *.java, or A*.java, or even A*.j*. You would just need a bit more code in the constructor or possibly the accept() method to analyze the argument. Our implementation of the accept() method here only returns true if the file name that is passed to it by the list()method has initial characters that are identical to name and the file extension is the same as that stored in extension.

In the modified example, we construct an object of our filter class using the string "F" as the file name prefix and the string ".java" as the extension. This version of the example will now only list files with names beginning with F and with the extension .java.

Creating and Modifying Files and Directories

There are methods defined in the File class that you can use to change the physical file by making it read-only or renaming it. There are also methods that enable you to create files and directories, and to delete them. The methods that provide these capabilities are:

Method

Description

renameTo(File path)

The file represented by the current object will be renamed to the path represented by the File object passed as an argument to the method. Note that this does not change the current File object in your program – it alters the physical file. Thus, the file that the File object represents will no longer exist after executing this method, because the file will have a new name, and possibly will be located in a different directory. If the file's directory in the new path is different from the original, the file will be moved. The method will fail if the directory in the new path for the file does not exist, or if you don't have write access to it. If the operation is successful the method will return true. Otherwise, it will return false

setReadOnly()

Sets the file represented by the current object as read-only and returns true if the operation is successful.

mkdir()

Creates a directory with the path specified by the current File object. The method will fail if the parent directory of the directory to be created does not already exist. The method returns true if it is successful and false otherwise.

mkdirs()

Creates the directory represented by the current File object, including any parent directories that are required. It returns true if the new directory is created successfully, and false otherwise. Note that even if the method fails, some of the directories in the path may have been created.

createNewFile()

Creates a new empty file with the pathname defined by the current File object as long as the file does not already exist. The method returns true if the file was created successfully. Note that this method will only create a file in an existing directory – it will not create any directories specified by the path.

createTempFile
(String prefix, String suffix, File directory)

This is a static method that creates a temporary file in the directory directory, with a name created using the first two arguments, and returns a File object corresponding to the file created. The string prefix represents the start of the file name and must be at least three characters long. The string suffix specifies the file extension. The file name will be formed from prefix followed by five or more generated characters, followed by suffix. If suffix is null, .tmp will be used. If prefix or suffix are too long for file names on the current system, they will be truncated, but neither will be truncated to less than three characters. If the directory argument is null, the system temporary directory will be used. If the file cannot be created, an IOException will be thrown. If prefix has less than three characters, an IllegalArgumentException will be thrown.

createTempFile
(String prefix, String suffix)

Equivalent to createTempFile(String prefix,
String suffix,
null).

delete()

This will delete the file or directory represented by the current File object and return true if the delete was successful. It won't delete directories that are not empty. To delete a directory, you must first delete the files it contains.

deleteOnExit()

Causes the file or directory represented by the current File object to be deleted when the program ends. This method does not return a value. The deletion will only be attempted if the JVM terminates normally. Once you call the method for a File object, the delete operation is irrevocable, so you will need to be cautious with this method.

Note that, in spite of the name, the files that you create by using the createTempFile() method are not necessarily temporary, as they will not be deleted automatically. You must use delete() or deleteOnExit() to ensure that files you no longer require are removed.

You can arrange for a temporary file to be deleted automatically at the end of the program by calling the deleteOnExit() method for the File object. For example, you might write:

File tempFile = File.createTempFile("list", null);
tempFile.deleteOnExit();

The first statement will create a temporary file with a name of the form listxxxxx.tmp in the default temporary directory. The xxxxx part of the name is generated automatically. Since we did not supply a suffix, the file extension will be .tmp by default. The second statement calls the deleteOnExit() method for tempFile, so we are assured that this file won't be left lying around after the program finishes. You can apply the deleteOnExit() method to any File object, not just those corresponding to temporary files, but do so with caution. As noted above, the delete is irrevocable once you have called the method!

We will be trying out some of these methods in examples later in this chapter. Now we understand how to define objects encapsulating a path in a Java program, we can move on to creating file stream objects. We will look at file output streams first.

Previous Next
JavaScript Editor Java Tutorials Free JavaScript Editor