How to Generate a Unique and Short File Name in Java

What is the best way to generate a unique and short file name in Java

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 prefix, 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.

generate files with unique names and write data into them

You could use a simple counter as a file prefix. You'd have to persist the current state of the counter between different runs of the program, though, e.g. also in the database. Here's a question dealing with the same issue and answers containing your current approach and others.

Unique File name using system time in Java?

You can use System.currentTimeInMillis

or

java.util.UUID.randomUUID()

How to create a unique file name?

public class MYValueRecorder {
String fileName;
myValueRecorder () {
Time t= new Time();
t.setToNow();
int timeFileMinute= t.minute;
int timeFileDate= t.yearDay;
int timeFileYear= t.year;

long timestamp=System.currentTimeMillis();

//creating file name
fileName= "MathsRaw-" +timeFileMinute + timeFileDate + timeFileYear + android.os.Build.SERIAL;
}

public void writeToFileRawData(String data) {
// do your stuff here, just don't initialize fileName again.
}
}

Use this, initialize a new class at the beginning of your session, then only use the writeToFileRawData method to write your data.

How to get short-filenames in Windows using Java?

Self Answer

There are related questions with related answers. I post this solution, however, because it uses Java(tm) code without the need for external libraries. Additional solutions for different versions of Java and/or Microsoft(R) Windows(tm) are welcome.

Main Concept

Main concept lies in calling CMD from Java(tm) by means of the runtime class:

cmd /c for %I in ("[long file name]") do @echo %~fsI

Solution

Tested on Java SE 7 running on Windows 7 system
(Code has been reduced for brevity).

    public static String getMSDOSName(String fileName)
throws IOException, InterruptedException {

String path = getAbsolutePath(fileName);

// changed "+ fileName.toUpperCase() +" to "path"
Process process =
Runtime.getRuntime().exec(
"cmd /c for %I in (\"" + path + "\") do @echo %~fsI");

process.waitFor();

byte[] data = new byte[65536];
int size = process.getInputStream().read(data);

if (size <= 0)
return null;

return new String(data, 0, size).replaceAll("\\r\\n", "");
}

public static String getAbsolutePath(String fileName)
throws IOException {
File file = new File(fileName);
String path = file.getAbsolutePath();

if (file.exists() == false)
file = new File(path);

path = file.getCanonicalPath();

if (file.isDirectory() && (path.endsWith(File.separator) == false))
path += File.separator;

return path;
}

Produce and resolve short file path

I want a collision free hash value

A hash is never collision free, but you can choose a hash algorith which is extremely unlikely to have collisions, as Jon Skeet explained.

How can I produce a shorter file path?

You need to distiguish two responsibilities.

  1. The hash value for the file gives you fast collision detection.
  2. Produce a short file path. Take a look at alphabet conversion theory and Java UrlShortener implementation.

To handle #2 you follow these steps:

a)Convert

  1. Save real file path in database
  2. You get a unique row ID for that
  3. Convert row ID to short string with encode()
  4. Use the short string as your short file path

b)Resolve


  1. Decode the short file path to an integer ID with decode()
  2. Look up real file path in database for given ID

Random file name generation function takes minutes to generate unique name

There are many problems with this code:

  • SELECT, then INSERT is prone to a race condition (between the two statements another process inserted the same ID). The clean way is to optimisticly insert a row, and retry on duplicate key errors, better still use a deterministicly unique function.
  • You prepare a new statement for every loop. The clean way is to prepare the statement once, then ececute it repeatedly with the different parameters. This is why they are called prepared statements
  • Your implementation uses PHP's rand() function, which produces wildly different qualities of randomness depending on PHP Version and OS. Use mt_rand();

I recommend you create the identifier inside the DB: See my answer to another SO question



Related Topics



Leave a reply



Submit