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.
- The hash value for the file gives you fast collision detection.
- 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
- Save real file path in database
- You get a unique row ID for that
- Convert row ID to short string with encode()
- Use the short string as your short file path
b)Resolve
- Decode the short file path to an integer ID with decode()
- 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
, thenINSERT
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. Usemt_rand();
I recommend you create the identifier inside the DB: See my answer to another SO question
Related Topics
Handling Static Variables in Multithreaded Java Program
Map Json String Column of a JPA Entity to Java Object Automatically
Scheduling a Job With Spring Programmatically (With Fixedrate Set Dynamically)
How to Avoid Thread.Sleep in Unit Tests
Kafka: Failed to Update Metadata After 60000 Ms
How to Use Limit in Spring Within SQL Query
Checking If a String Is Contained in an Enum Set in O(1)
Filling a List With All Enum Values in Java
How to Get File Extension from Content Type
I Want to Execute Code Every X Seconds, But Handler.Postdelayed Not Working
Escaping New Line Character Within SQL Query
How to Stop the Items Duplication in Recyclerview Android
How to Generate a Unique and Short File Name in Java
Unable to Deploy Spring Boot 2 Application Due to Hikaripool Exception During Pool Initialization
Placing a Jlabel At a Specific X,Y Coordinate on a Jpanel
Webdriver/Pageobject/Findby: How to Specify Xpath With Dynamic Value
Disable Spring Security Config Class for @Webmvctest in Spring Boot
Change the Textview Text Color When Button Is Clicked in Android