tags:

views:

1713

answers:

10

I don't necessarily want to use UUIDs since they are fairly long.

The file just needs to be unique within its directory.

One thought which comes to mind is to use File.createTempFile(String prefix, String suffix), but that seems wrong because the file is not temporary.

The case of two files created in the same millisecond needs to be handled.

+1  A: 

Why not just use something based on a timestamp..?

Galwegian
What if two files are created in the same millisecond?
Jeff Bloom
Retry for the failure, the new timestamp will then be different
JRL
@Jeff. Just detect the conflict and try again until there is no conflict; in practice this should be very rare.
Software Monkey
If you're going to detect the conflict anyway, just generate a random filename without worrying about the time - see my answer, for example. It's still going to be pretty rare that you generate the same filename with (say) 8 characters in :)
Jon Skeet
+3  A: 

I use the timestamp

i.e

new File( simpleDateFormat.format( new Date() ) );

And have the simpleDateFormat initialized to something like as:

new SimpleDateFormat("File-ddMMyy-hhmmss.SSS.txt");

EDIT

What about

new File(String.format("%s.%s", sdf.format( new Date() ),
                                random.nextInt(9)));

Unless the number of files created in the same second is too high.

If that's the case and the name doesn't matters

 new File( "file."+count++ );

:P

OscarRyz
Yes, but what if two files are created in the same second, or millisecond.
Jeff Bloom
+9  A: 

Well, you could use the 3-argument version: File.createTempFile(String prefix, String suffix, File directory) which will let you put it where you'd like. Unless you tell it to, Java won't treat it differently than any other file. The only drawback is that the filename is guaranteed to be at least 8 characters long (minimum of 3 characters for the suffix, plus 5 or more characters generated by the function).

If that's too long for you, I suppose you could always just start with the filename "a", and loop through "b", "c", etc until you find one that doesn't already exist.

Pesto
A: 

Have a look at my answer to this similar (but .NET) question.

Basically, create a random filename in any normal way, using an instance of java.util.Random or whatever other RNG you want to use. Then attempt to create the file - if it fails, repeat until it works.

Jon Skeet
Why do so many peopple try to archive uniquenes through Randoms ?
HaBaLeS
Because when you've got the file system to use as your atomic check, it's all that's required. Could you explain in what way this wouldn't work?
Jon Skeet
Jon's answer is quite helpful. It should voted up, not down. I am going to end up using File.createTempFile(String prefix, String suffix, File directory), however I might use Jon's method to create directory names if there is not a similar createTemp for directories.
Jeff Bloom
This http://thedailywtf.com/Articles/The-Quest-for-the-Unique-ID.aspx short story should explain why random number generation of Unique IDs is possibly dangerous. As you don't know the system an how many files will be generated you can run out of random numbers and even worse, it will take ages to find a new "unique" number if you have a lot of files.
HaBaLeS
Just how many files would you expect to have in the directory before this becomes a real problem? Suppose 8 characters, A-Z and 0-9, i.e. 36^8 possibilities. Even with the birthday paradox, that's an awfully lot of combinations... what are the chances of having to try even 3 times, with (say) a billion files? Pretty slim. Now show me a use case where you'd even *have* a billion files. The DailyWTF article is a different situation, where you're dealing with a database: databases provide better ways of doing this. (Continued.)
Jon Skeet
Also note the difference in the set of possible IDs - a million vs 36^8. It's not hard to imagine a single table with close to a million entries. It's pretty hard to imagine a directory with close to 36^8 files in.
Jon Skeet
+1  A: 

Look at the File javadoc, the method createNewFile will create the file only if it doesn't exist, and will return a boolean to say if the file was created.

You may also use the exists() method:

    int i = 0;
    String filename = Integer.toString(i);
    File f = new File(filename);
    while (f.exists()) {
        i++;
        filename = Integer.toString(i);
        f = new File(filename);
    }
    f.createNewFile();
    System.out.println("File in use: " + f);
pgras
A: 

How about generate based on time stamp rounded to the nearest millisecond, or whatever accuracy you need... then use a lock to synchronize access to the function.

If you store the last generated file name, you can append sequential letters or further digits to it as needed to make it unique.

Or if you'd rather do it without locks, use a time step plus a thread ID, and make sure that the function takes longer than a millisecond, or waits so that it does.

justinhj
+1  A: 

Combining other answers, why not use the ms timestamp with a random value appended; repeat until no conflict, which in practice will be almost never.

For example: File-ccyymmdd-hhmmss-mmm-rrrrrr.txt

Software Monkey
+1  A: 

I'd use Apache Commons Lang library (http://commons.apache.org/lang).

There is a class org.apache.commons.lang.RandomStringUtils that can be used to generate random strings of given length. Very handy not only for filename generation!

Here is the example:

String ext = "dat";
File dir = new File("/home/pregzt");
String name = String.format("%s.%s", RandomStringUtils.randomAlphanumeric(8), ext);
File file = new File(dir, name);
pregzt
A: 

If you have access to a database, you can create and use a sequence in the file name.

select mySequence.nextval from dual;

It will be guaranteed to be unique and shouldn't get too large (unless you are pumping out a ton of files).

Shane
A: 

It looks like you've got a handful of solutions for creating a unique filename, so I'll leave that alone. I would test the filename this way:

    String filePath;
    boolean fileNotFound = true;
    while (fileNotFound) {
        String testPath = generateFilename();

        try {
            RandomAccessFile f = new RandomAccessFile(
                new File(testPath), "r");
        } catch (Exception e) {
            // exception thrown by RandomAccessFile if 
            // testPath doesn't exist (ie: it can't be read)

            filePath = testPath;
            fileNotFound = false;
        }
    }
    //now create your file with filePath
Peter Cowan