10

I have a multi-threaded Java program that creates hundreds of temporary files in seconds. The files are placed in /tmp and are named using System.nanoTime().

Are the file names guaranteed to be unique?

NPE
  • 486,780
  • 108
  • 951
  • 1,012
Danny Choi
  • 251
  • 1
  • 4
  • 13
  • not always but most probably. – Andreas Dolk Mar 19 '13 at 07:25
  • 3
    @Andreas_D - or to put it another way, the probability of two generated filenames being equal is small enough that it won't be picked up in testing. Sod's law says that the problem will then come back and bite you in production. – Stephen C Mar 19 '13 at 07:35
  • 1
    Stephen, that was my intention with the comment. No gurantee. For unique names: use a sequence. Or concatenate random numbers to the nano value to further decrease the probability of name clashs. Or: simply check if the file exists and generate a new name, if this should be the case. – Andreas Dolk Mar 19 '13 at 07:44

4 Answers4

18

No, there is no guarantee that every call to System.nanoTime() will return a unique value.

Use File.createTempFile() or Files.createTempFile() instead. They are designed for just this purpose, and will generate unique file names for you.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • oh.. really?? Could you tell me any method instead of it? cheers mate. – Danny Choi Mar 19 '13 at 07:29
  • @DannyChoi: `createTempFile()`, as explained in my answer. – NPE Mar 19 '13 at 07:30
  • yes I am using ... temp = File.createTempFile("temp", Long.toString(System.nanoTime())); – Danny Choi Mar 19 '13 at 07:31
  • 6
    You don't need to give a unique string to `createTempFile`; it's supposed to create that for you. You can simply use `File.createTempFile("temp", null);` – Dolda2000 Mar 19 '13 at 07:33
  • 1
    Both the `prefix` and the `suffix` argument are just a convenience extended to you by the API, so you can have the unique string placed anywhere inside the filename. – Marko Topolnik Mar 19 '13 at 07:38
4

As for your original question

No, not really. Your threads could run in parallel at the same time on a multi CPU/core system and thus there is no guarantee for unique values.

Plus, nanoTime() is only as accurate as the underlaying clock. Which means, two sequential calls to nanoTime could return the same value.

Quote from the API: "No guarantees are made about how frequently values change."

Solution

You should use File.createTempFile() and let Java handle the uniqueness of your temp files.

// create temp file in /tmp with prefix  tmpfile and suffix .txt
File file = File.createTempFile("tmpfile", ".txt", new File("/tmp"));

// deletes file when the virtual machine terminate
file.deleteOnExit();

You could even use the thread id or something similar as prefix, to keep those temFiles appart.

phisch
  • 4,571
  • 2
  • 34
  • 52
3

If you need unique file names for temporary files, use File.createTempFile(prefix, suffix, directory).

Thilo
  • 257,207
  • 101
  • 511
  • 656
1

If you run your thread system on a machine that can create more than one file per nanosecond, you might/will have name collisions.

A solution for this might be to store a static "index counter" which you can use to prepend/append to a filename.

As an example, your filename could be System.nanoTime() + "x" + SomeClassName.index() where the index() method would return the value of your index, while also incrementing it. (You can ditch the "x" by making the index() return a String or converting the value to one).

It will not matter if the "index counter" is reset to 0 every time the program re-launches (I really doubt that a JVM instance can start in under a nanosecond).

Just make sure to make the index() method thread-safe.

EDIT:

My solution provides a way for you to generate the unique file names. I am using a similar solution (with "System.currentTimeMillis()" instead of System.nanoTime()) to generate unique IDs for variables that have a temporary representation in a database and it works like a charm (using a prefix, it also allows for bulk deletion of certain entries in the DB, not just emptying the DB).

If you're not interested in the filenames themselves, but are interested only in having/using temporary files, I'd go with NPE's solution.

lucian.pantelimon
  • 3,673
  • 4
  • 29
  • 46