
java.io.tmpdir Inconsitency
January 26, 2007Summary
A description of a platform inconsistency in Java that can cause problems when building file paths that use the temp directory.
The Temp Directory
Java has a way of giving you the path to the temp directory in a platform neutral way. You simply ask the system for the “java.io.tmpdir” property and you’re good to go. Here’s an example of code that does that and prints the result.
The Code
package tmp;
public class TempDir {
public static void main(String[] args) {
String tmpDir = System.getProperty(”java.io.tmpdir”);
System.out.println(”java.io.tmpdir: [" + tmpDir + "]“);
}
}
The Output
On Windows: java.io.tmpdir:[C:\DOCUME~1\joshua\LOCALS~1\Temp\]
On Solaris: java.io.tmpdir:[/var/tmp/]
On Linux: java.io.tmpdir: [/tmp]
On Mac OS X: java.io.tmpdir: [/tmp]
As you can see, it gives you the temp directory that is appropriate to the platform. Now you just use it. Well, almost. Take a look at those paths again. The Linux and Mac OS X ones vary slightly from the others. Not much, but just enough to cause your application to fail if you don’t take precautions. You see it? Yep, the Linux and Mac OS X output don’t end in the file separator (forward slash)! So when you build paths using code like the following…
String myPath = System.getProperty("java.io.tmpdir") + "some"
+ File.separator + "place" + File.separator + "somefile.txt");
…they fail.
On Windows:C:\DOCUME~1\joshua\LOCALS~1\Temp\some\place\somefile.txt
On Solaris: /var/tmp/some/place/somefile.txt
On Linux: /tmpsome/place/somefile.txt
On Mac OS X: /tmpsome/place/somefile.txt
tmp and some get slammed together on Linux and Mac OS X as tmpsome without the file separator between them. This means that if you want to use the java.io.tmpdir property to build a path, you have to check for the file separator at the end of the String and add it if it’s not there.
The other option is just to add the File.separator no matter what when building paths with java.io.tmpdir. In limited tests on Windows, Solaris, Linux and Mac OS X it looks like the operating system handles doubled file separators without problems. It simply swallows the second one and acts as if it was a single file separator.
Real World
So where would this come up? Actually, the reason that I came across it is that I’ve started using the temp directory more often in applications when I need a throw away space. The temp directory is especially useful when used in coordination with the java.io.File.deleteOnExit() method. This method lets you delete a file referenced by a java.io.File reference when the JVM exits. This is very nice when you only need a file for the duration of the running of the application. While I tried to avoid direct file IO in unit testing by using streams and the like, if you are testing classes whose primary function is file IO, then you really need to touch the disk to test effectively. In these cases I usually create a directory within the temp directory and create test files there that will either be deleted in my JUnit tearDown() method or, at the very least, when the JVM exits.
Bug or Feature?
So why do Linux and Mac OS X vary in this case? Is it a bug in the Linux and Mac OS X implementations of the JDK? Or a bug in the Windows and Solaris implementations? Not according to Sun. I did a little digging and it seems that someone else discovered this little annoyance and reported it as a bug. The state of the issue is “Closed, not a bug”. A feature then? I guess. Touching the system with things like System.getProperty() is always problematic, but it seems that these properties should have been defined a little more rigorously so the inconsistency wouldn’t be there. In any case, hopefully people will run across this “feature” with a search engine hitting on this blog entry instead of at 5pm on a Friday when they try to run their polished Java app on Linux or Mac OS X and it fails due to a missing forward slash.
Joshua Smith
Resources:
Java Application Development on Linux at Amazon
Java Programming on Linux at Amazon
Mac OS X for Java Geeks at Amazon
Keywords:
java java.io.tmpdir System.getProperty temporary temp tmp directory platform consistency inconsistency Linux Mac OS X Windows Solaris
Technorati Tags: java
I got into this problem too. I believe that by convention, directory path needs to start with but not end with “/”.
For example, mypath=”/foo/haa”, or yourpath=”/hoge/hoge”.
This allows the concatenation of the directory path to be cleaner. ourpath=mypath + yourpath. And gives programmer choice to add or not add slash (instead of having no choice).
So, I believe Windows and AIX should return the path without the trailing slash as well. If the slash doesn’t have to be there, why should it exist, really?
It’s not really good style to append paths via string concatenation. Better use the java.io.File constructor:
new File(System.getProperty(”java.io.tmpdir”), “file.txt”));
Sweet, I was having this problem and a google search brought me here. Thanks for the info!
Glad it was helpful! :-)