h1

java.io.tmpdir Inconsitency

January 26, 2007

Summary

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:

19 comments

  1. 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?


  2. 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”));


  3. Sweet, I was having this problem and a google search brought me here. Thanks for the info!


  4. Glad it was helpful! :-)


  5. I faced similar problems on HP-UX

    On HP-UX: java.io.tmpdir:[/var/tmp/]

    greets


  6. Clemens,

    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


  7. It 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?


  8. Clemens,
    thanks a lot. Google took me right here, where I got a precise answer!


  9. 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.


  10. Yes 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). :(.


  11. […] 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 […]


  12. 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…


  13. Quite 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. :)


  14. I’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.


  15. Makes 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! :-)


  16. […] 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 […]


  17. Hello, 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. :(


  18. Helpful :)


  19. Nice, by creating temp dir on mac os created directory has no write access. Is there any ways to create temp directory with write access?



Leave a reply to Rob Manning Cancel reply