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?
by Soichi Hayashi June 29, 2007 at 3:07 pmIt’s not really good style to append paths via string concatenation. Better use the java.io.File constructor:
by Clemens August 16, 2007 at 9:23 amnew 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!
by javadude June 23, 2008 at 6:26 pmGlad it was helpful! :-)
by Josh June 25, 2008 at 11:29 amI faced similar problems on HP-UX
On HP-UX: java.io.tmpdir:[/var/tmp/]
greets
by Fábio Franco Uechi August 12, 2008 at 11:01 amClemens,
I thought the same thing; use File API instead of concatenating strings then get the path from the constructed File object. However, while this works find in a Java application, it doesn’t work so well in an Ant build script that references java.io.tmpdir to place temporary files. So this blog entry is still useful.
Rob
by Rob Manning December 29, 2008 at 8:52 amIt baffles me why people don’t use:
fullpath = new File(parentDir, relativePath)
to concatenate file paths. Are you just trying to make your life miserable?
by Adrian March 13, 2009 at 8:05 amClemens,
by Christian July 10, 2009 at 3:03 amthanks a lot. Google took me right here, where I got a precise answer!
Even in Java, sometimes you need to pass a String path as parameter, because the library doesn´t have and method with File version. And contructing a java.io.File just to concatenate the path isn´t a good solution, IMHO.
by Leonel Martins July 10, 2009 at 10:06 amYes of course. I too faced this. No need to go all these. Just look at the “System.getProperty(“line.separator”)”. It is of 1 character in Unix and its flavors whereas it is of 2 characters in Windows (\r\n). :(.
by Raghavan alias Saravanan M September 15, 2009 at 10:57 am[…] if you know of any inconsistencies across different environments (e.g. like java.io.tmpdir that might or might not endswith a file seperator) – make a guess – let me […]
by The Final Take On Java System Properties Molindo Techblog - Molindo Techblog – formerly known as talk-on-tech.blogspot.com November 26, 2009 at 5:47 am…
On Windows 7: java.io.tmpdir:[C:\Users\joshua\AppData\Local\Temp\]
On Windows 2k/XP english-version: java.io.tmpdir:[C:\DOCUME~1\joshua\LOCALS~1\Temp\]
On Windows 2k/XP german-version: java.io.tmpdir:[C:\DOKUME~1\joshua\LOKALE~1\Temp\]
On Solaris: java.io.tmpdir:[/var/tmp/]
On Linux: java.io.tmpdir: [/tmp]
On Mac OS X: java.io.tmpdir: [/tmp]
On Mac OS X 10.6 java.io.tmpdir: [/private/Users/joshua/…
still some possibilities left…
by anon July 30, 2010 at 5:35 pmQuite helpful. Thanks! For the longest time I’ve been depending on my own “temp” directories and not on the built-in by Java. At least I’m going to use the standard from hereon. :)
by Ronx August 19, 2010 at 1:38 amI’ve personally never encountered this particular situation, primarily because I don’t like to directly construct paths via string concatenation. Knowing the inherit problems between file-systems of disparate operating systems, I prefer to leave this sort of thing to Java itself to figure out:
File tmpDir = new File(System.getProperty(“java,io.tmpdir”));
.
.
.
File tmpFile = new File(tmpDir, “myfile.tmp”);
With the above, trailing slashes are completely irrelevant.
by Nathan March 23, 2011 at 5:21 pmMakes sense for a path to end with a slash, doesn’t it? Look at root, the most important path on *nix: “/” — it ends with a slash! :-)
by Juan Uys May 3, 2011 at 7:23 am[…] if you know of any inconsistencies across different environments (e.g. like java.io.tmpdir that might or might not endswith a file seperator) – make a guess – let me […]
by The Final Take On Java System Properties Molindo Techblog - Molindo Techblog – formerly known as talk-on-tech.blogspot.com December 20, 2011 at 4:34 amHello, i tried to use “System.getProperty(“java.io.tmpdir”)” to get the path of temporary directory in Win7 64 bit system but in return m getting the value “C:\Window\Temp”. Am i doing something wrong. PLZZZZZ help. :(
by Bhoomika April 13, 2012 at 2:33 amHelpful :)
by first June 4, 2012 at 1:24 amNice, by creating temp dir on mac os created directory has no write access. Is there any ways to create temp directory with write access?
by kwtrio June 30, 2012 at 12:54 am