| You have learned how to read and write data from a file. However, there is more to file management than reading and writing. The File class encapsulates the functionality that you will need in order to work with the file system on the user's machine. For example, you use the File class to find out when a file was last modified or to remove or rename the file. In other words, the stream classes are concerned with the contents of the file, whereas the File class is concerned with the storage of the file on a disk. NOTE
The simplest constructor for a File object takes a (full) file name. If you don't supply a path name, then Java uses the current directory. For example, File f = new File("test.txt"); gives you a file object with this name in the current directory. (The "current directory" is the current directory of the process that executes the virtual machine. If you launched the virtual machine from the command line, it is the directory from which you started the java executable.) A call to this constructor does not create a file with this name if it doesn't exist. Actually, creating a file from a File object is done with one of the stream class constructors or the createNewFile method in the File class. The createNewFile method only creates a file if no file with that name exists, and it returns a boolean to tell you whether it was successful. On the other hand, once you have a File object, the exists method in the File class tells you whether a file exists with that name. For example, the following trial program would almost certainly print "false" on anyone's machine, and yet it can print out a path name to this nonexistent file. import java.io.*; public class Test { public static void main(String args[]) { File f = new File("afilethatprobablydoesntexist"); System.out.println(f.getAbsolutePath()); System.out.println(f.exists()); } } There are two other constructors for File objects: File(String path, String name) which creates a File object with the given name in the directory specified by the path parameter. (If the path parameter is null, this constructor creates a File object, using the current directory.) Finally, you can use an existing File object in the constructor: File(File dir, String name) where the File object represents a directory and, as before, if dir is null, the constructor creates a File object in the current directory. Somewhat confusingly, a File object can represent either a file or a directory (perhaps because the operating system that the Java designers were most familiar with happens to implement directories as files). You use the isDirectory and isFile methods to tell whether the file object represents a file or a directory. This is surprising in an object-oriented system, you might have expected a separate Directory class, perhaps extending the File class. To make an object representing a directory, you simply supply the directory name in the File constructor: File tempDir = new File(File.separator + "temp"); If this directory does not yet exist, you can create it with the mkdir method: tempDir.mkdir(); If a file object represents a directory, use list() to get an array of the file names in that directory. The program in Example 12 7 uses all these methods to print out the directory substructure of whatever path is entered on the command line. (It would be easy enough to change this program into a utility class that returns a vector of the subdirectories for further processing.) TIP
Example 12-7. FindDirectories.java 1. import java.io.*; 2. 3. public class FindDirectories 4. { 5. public static void main(String[] args) 6. { 7. // if no arguments provided, start at the parent directory 8. if (args.length == 0) args = new String[] { ".." }; 9. 10. try 11. { 12. File pathName = new File(args[0]); 13. String[] fileNames = pathName.list(); 14. 15. // enumerate all files in the directory 16. for (int i = 0; i < fileNames.length; i++) 17. { 18. File f = new File(pathName.getPath(), fileNames[i]); 19. 20. // if the file is again a directory, call the main method recursively 21. if (f.isDirectory()) 22. { 23. System.out.println(f.getCanonicalPath()); 24. main(new String [] { f.getPath() }); 25. } 26. } 27. } 28. catch(IOException e) 29. { 30. e.printStackTrace(); 31. } 32. } 33. } Rather than listing all files in a directory, you can use a FileNameFilter object as a parameter to the list method to narrow down the list. These objects are simply instances of a class that satisfies the FilenameFilter interface. All a class needs to do to implement the FilenameFilter interface is define a method called accept. Here is an example of a simple FilenameFilter class that allows only files with a specified extension: public class ExtensionFilter implements FilenameFilter { public ExtensionFilter(String ext) { extension = "." + ext; } public boolean accept(File dir, String name) { return name.endsWith(extension); } private String extension; } When writing portable programs, it is a challenge to specify file names with subdirectories. As we mentioned earlier, it turns out that you can use a forward slash (the UNIX separator) as the directory separator in Windows as well, but other operating systems might not permit this, so we don't recommend using a forward slash. CAUTION
It is much better to use the information about the current directory separator that the File class stores in a static instance field called separator. (In a Windows environment, this is a backslash (\); in a UNIX environment, it is a forward slash (/). For example: File foo = new File("Documents" + File.separator + "data.txt") Of course, if you use the second alternate version of the File constructor File foo = new File("Documents", "data.txt") then the constructor will supply the correct separator. The API notes that follow give you what we think are the most important remaining methods of the File class; their use should be straightforward. java.io.File 1.0
java.io.FilenameFilter 1.0
|