Missing or Broken Functionality
Since 1997, users have been trying to convince Sun to do something about
; many believe that global change of a current directory in an application is a dangerous operation. For example, beans in an app server may inadvertently change global settings and destroy the functionality that other beans use. Other languages and other types of applications allow the behavior, and operating systems readily provide this functionality.
A naïve solution would be to set the system property,
user.dir, which is used occasionally to resolve relative path problems. Unfortunately, public opinion about whether this solution is effective or not is split. As a result, Java still has a weird behavior. For instance, consider the following piece of code:
// create a temp directory
// try to chdir to c:\tmp
// subdirectory, relative path
File subdir = new File("tmpdir");
// check that its absolute path is what we want
// check that it is our new directory
// see that we were grossly misled
Here, the code resolves the file's relative path to absolute path in different ways in its java.io and native methods.
File.setLastModified(), a seemingly elementary operation, does not always work. I had to add a static
setLastModified(File file) to the library to bypass this bug. It does the trick recommended in the aforementioned bug report (do
System.gc() if the operation did not work during the first attempt).
Two other methods,
chown, will probably never be implemented, since they are perceived as platform-dependent. I believe that the Java community could at least tolerate POSIX as a platform. The
chmod method is represented in
File.setReadOnly() (with no "Back" button);
chown is just missing.
Often, all a Java developer needs to do with a file is read its entire contents as a byte array, a char array, or a string, or write an array or a string to a file (version: append to the end of the file). The following is a whole bunch of useful methods included in the Files utility class:
readBytesFromFile(String filename) (This one uses memory-mapped files introduced with java.nio.)
readStringFromFile(File file, String encoding)
writeToFile(bytedata, String fileTo)
writeToFile(chardata, String fileTo)
writeToFile(CharSequence data, String fileTo)
writeToFile(InputStream is, String fileTo) (This one pipes bytes from an input stream to a file.)
appendBytesToFile(bytedata, String fileTo) a.k.a.
appendToFile, appendBytesToFile(chardata, String fileTo) (This one takes lower bytes from
appendToFile(chardata, String fileTo)
appendToFile(CharSequence data, String fileTo)
Memory-mapped File Copy
Java.nio offers an interesting method for copying files. Instead of reading each byte and writing it to another file, you can memory map the files. The whole copy operation may look like this:
FileInputStream is = new FileInputStream(from);
FileOutputStream os = makeFile(to);
os.getChannel().transferFrom(is.getChannel(), 0, from.length());
I tried to check whether one gains any advantage besides saving memory from using this, but benchmarking file copy is not easy. On a machine with 1GB of memory, I created eight 100MB files. I then copied them, one after another, to ensure that there was no trace of the first file in any cache. I timed only the first of these files and repeated the operation ten times, both with memory mapping and without. I spent two hours running it all and produced the following results:
- It took 16.897558069 seconds to copy with NIO.
- It took 17.638485729 seconds to copy without NIO.
- NIO is 740.92766 milliseconds faster.