Download (direct link):
Item 20: When File.renameTo() Won't10
The File class and specifically the File.renameTo() method suffers from pitfalls in both design and implementation. Many pitfalls stem from confusion regarding the expected behavior of classes in the Java libraries. Unfortunately, the input/output (IO) classes in Java have been prone to significant revision as the Java platform has evolved. An early overhaul added readers and writers to the input and output streams to distinguish between character-based IO and byte-based IO. With JDK 1.4, another overhaul has taken place, adding a lower layer of high-performance access via Channel classes. Figure
20.1 displays the major file-related classes in the java.io and java.nio packages.
Unfortunately, just the fact that there are five classes and two interfaces all pertaining to different facets of a file increases the complexity of using these classes properly. That is especially true if the distinction between classes is small or if the role of the class is ill defined. Let's examine each class and its purpose:
Figure 20.1 File-related classes in the Java class libraries.
10 This pitfall was first published by JavaWorld (www.javaworld.com) in the article, “Practice makes perfect" November 2001 (http://www.javaworld.com/javaworld/jw-11-2001 /jw-1116-traps-p2.html) and is reprinted here with permission. The pitfall has been updated from reader feedback.
152 Item 20
File. Present since JDK 1.0, a class that represents a file or directory pathname. This class contains a wide array of methods to test characteristics of a file, delete a file, create directories, and, of course, rename a file. Unfortunately, this class suffers from a vague scope in that it incorporates behaviors of a directory entry, like isFile(), isDirectory(), and lastModified(), and behaviors of a physical file like createNewFile(), delete(), and renameTo(). We will discuss this more later.
FilenameFilter. Present since JDK 1.0, an interface to test the occurrence of a list of File objects via the File.list() method and FileDialog.setFilename-Filter() method. The confusion over scope stated above is evident in the contradiction between this interface and the next one (FileFilter) in terms of their names. This interface has a single method called accept() that receives a File object representing a directory and a String representing the name of the file to filter on.
FileFilter. Added in JDK 1.2, an interface to filter in the same manner as FilenameFilter except that the accept() method receives only a single File object. Unfortunately, this interface is a prime example of a superfluous convenience interface that does more harm than good because of the new name. It would have been far better to follow the precedent of the awt package where LayoutManager2 extends LayoutManager to add methods. The difference between the two design strategies is that the LayoutManager interfaces are clearly semantically congruent, whereas FilenameFilter and FileFilter are not.
FileDescriptor. A class to provide an opaque handle to the operating system-specific File data structure. As its name implies, this class is a very thin abstraction over an operating system structure. The class only has two methods. As a general design rule, it would be preferable to combine our abstractions of a physical file into a single class. Unfortunately, the requirements of backward compatibility cause future developers to suffer with multiple abstractions. Since the New IO package (NIO), split IO operations at the package level (which also spoils the platform's cohesiveness), there is an opportunity to start from scratch with new classes in the NIO package.
FilePermission. A class to represent access to a file directory. This was part of the 1.2 fine-grained security mechanisms—again, a nice candidate for conceptual consolidation.
RandomAccessFile. Present since JDK 1.0, a class that represents the characteristics and behaviors (taken from the C standard library) of a binary file. This allows low-level reading and writing of bytes to a file from any random file position. This class stands on its own and does not fit in to the IO stream metaphor and does not interact with those classes. It is interesting to note that the word "File" in this class name actually refers to a physical file and not just its name. Unfortunately, this package lacks such consistency.
FileChannel. Added to JDK 1.4, a class to provide a high-performance pathway for reading, writing, mapping, and manipulating a file. You get a FileChannel from a FilelnputStream, FileOutputStream, or RandomAccessFile class. A key benefit of this class is the ability to map a file to memory. Item 2
When File.renameTo() Won't 153
examined the NIO performance improvements. Lastly, a region of the file (or the whole file) may be locked to prevent access or modification by other programs via methods that return a FileLock object.