wake-up-neo.com

Was ist der beste Weg, um einen eindeutigen und kurzen Dateinamen in Java zu generieren?

Ich möchte nicht unbedingt UUIDs verwenden, da sie ziemlich lang sind.

Die Datei muss nur innerhalb des Verzeichnisses eindeutig sein.

Ein Gedanke, der mir einfällt, ist die Verwendung von File.createTempFile(String prefix, String suffix), aber das scheint falsch zu sein, da die Datei nicht temporär ist.

Der Fall von zwei Dateien, die in derselben Millisekunde erstellt wurden, muss behandelt werden.

65
Jeff Bloom

Nun, Sie können die 3-Argument-Version verwenden: File.createTempFile(String prefix, String suffix, File directory) , mit der Sie sie an die gewünschte Stelle setzen können. Wenn Sie es nicht sagen, behandelt Java es nicht anders als jede andere Datei. Der einzige Nachteil ist, dass der Dateiname garantiert mindestens 8 Zeichen lang ist (mindestens 3 Zeichen für das Präfix plus 5 oder mehr Zeichen, die von der Funktion generiert werden).

Wenn das für Sie zu lang ist, können Sie immer mit dem Dateinamen "a" beginnen und "b", "c" usw. durchlaufen, bis Sie einen finden, der noch nicht vorhanden ist.

79
Pesto

Ich würde Apache Commons Lang-Bibliothek verwenden (  http://commons.Apache.org/lang).

Es gibt eine Klasse org.Apache.commons.lang.RandomStringUtils, mit der zufällige Zeichenfolgen gegebener Länge generiert werden können. Sehr praktisch nicht nur für die Dateinamengenerierung!

Hier ist das Beispiel:

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);
27

Ich benutze den Zeitstempel

d.h.

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

Und haben Sie das simpleDateFormat wie folgt initialisiert:

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

EDIT

Wie wäre es mit

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

Es sei denn, die Anzahl der in derselben Sekunde erstellten Dateien ist zu hoch. 

Wenn das der Fall ist und der Name keine Rolle spielt

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

: P

11
OscarRyz

Das funktioniert für mich:

String generateUniqueFileName() {
    String filename = "";
    long millis = System.currentTimeMillis();
    String datetime = new Date().toGMTString();
    datetime = datetime.replace(" ", "");
    datetime = datetime.replace(":", "");
    String rndchars = RandomStringUtils.randomAlphanumeric(16);
    filename = rndchars + "_" + datetime + "_" + millis;
    return filename;
}

// USE:

String newFile;
do{
newFile=generateUniqueFileName() + "." + FileExt;
}
while(new File(basePath+newFile).exists());

Ausgabedateinamen sollten folgendermaßen aussehen:

2OoBwH8OwYGKW2QE_4Sep2013061732GMT_1378275452253.Ext
10

Wenn Sie Zugriff auf eine Datenbank haben, können Sie im Dateinamen eine Sequenz erstellen und verwenden. 

select mySequence.nextval from dual;

Es wird garantiert einzigartig sein und sollte nicht zu groß werden (es sei denn, Sie tonnenweise Dateien herauspumpen).

5
Shane

Schauen Sie sich die Datei File javadoc an. Die Methode createNewFile erstellt die Datei nur, wenn sie nicht vorhanden ist, und gibt einen Boolean-Wert zurück, um anzugeben, ob die Datei erstellt wurde.

Sie können auch die exists () -Methode verwenden:

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);
5
pgras

Warum nicht einfach etwas basierend auf einem Zeitstempel verwenden ..?

2
Galwegian

Wenn Sie andere Antworten kombinieren, verwenden Sie den ms-Zeitstempel und einen zufälligen Wert. Wiederhole es bis zu keinem Konflikt, was in der Praxis so gut wie nie sein wird.

Zum Beispiel: File-ccyymmdd-hhmmss-mmm-rrrrrr.txt

2
Lawrence Dol
    //Generating Unique File Name
    public String getFileName() {
        String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date());
        return "PNG_" + timeStamp + "_.png";
    }
1
LEGEND MORTAL

Ich verstehe, dass ich zu spät komme, um diese Frage zu beantworten. Aber ich denke, ich sollte dies so ausdrücken, dass es sich von anderen Lösungen unterscheidet.

Wir können Threadnamen und aktuelle Zeitstempel als Dateinamen verketten. Dies ist jedoch ein Problem, da ein Thread-Name ein Sonderzeichen wie "\" enthält, das Probleme beim Erstellen des Dateinamens verursachen kann. So können wir spezielle Zeichen aus dem Threadnamen entfernen und dann den Threadnamen und den Zeitstempel verketten

fileName = threadName(after removing special charater) + currentTimeStamp
0
Roshan

Das funktioniert auch

String logFileName = new SimpleDateFormat("yyyyMMddHHmm'.txt'").format(new Date());

logFileName = "loggerFile_" + logFileName;
0
T.Akshay

Problem ist die Synchronisation. Konfliktregionen voneinander trennen.

Benennen Sie die Datei wie folgt: (server-name)_(thread/process-name)_(millisecond/timestamp).(extension)
Beispiel: aws1_t1_1447402821007.png

0
smit thakkar

Es sieht so aus, als hätten Sie eine Handvoll Lösungen, um einen eindeutigen Dateinamen zu erstellen, also lass ich das alleine. Ich würde den Dateinamen auf diese Weise testen:

    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
0
Peter Anthony

Wie wäre es, basierend auf einem Zeitstempel, der auf die nächste Millisekunde gerundet wird, zu generieren, oder wie auch immer die Genauigkeit ist, die Sie benötigen ... Verwenden Sie dann eine Sperre, um den Zugriff auf die Funktion zu synchronisieren.

Wenn Sie den zuletzt generierten Dateinamen speichern, können Sie nach Bedarf fortlaufende Buchstaben oder weitere Ziffern hinzufügen, um ihn eindeutig zu machen. 

Wenn Sie dies lieber ohne Sperren tun möchten, verwenden Sie einen Zeitschritt plus eine Thread-ID und stellen Sie sicher, dass die Funktion länger als eine Millisekunde dauert oder wartet, bis sie ausgeführt wird.

0
justinhj

Warum nicht synchronisiert verwenden, um Multi-Thread zu verarbeiten. Hier ist meine Lösung. Sie kann einen kurzen Dateinamen generieren und ist eindeutig.

private static synchronized String generateFileName(){
    String name = make(index);
    index ++;
    return name;
}
private static String make(int index) {
    if(index == 0) return "";
    return String.valueOf(chars[index % chars.length]) + make(index / chars.length);
}
private static int index = 1;
private static char[] chars = {'a','b','c','d','e','f','g',
        'h','i','j','k','l','m','n',
        'o','p','q','r','s','t',
        'u','v','w','x','y','z'};

blies ist Hauptfunktion für den Test, es ist Arbeit.

public static void main(String[] args) {
    List<String> names = new ArrayList<>();
    List<Thread> threads = new ArrayList<>();
    for (int i = 0; i < 100; i++) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    String name = generateFileName();
                    names.add(name);
                }
            }
        });
        thread.run();
        threads.add(thread);
    }

    for (int i = 0; i < 10; i++) {
        try {
            threads.get(i).join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    System.out.println(names);
    System.out.println(names.size());

}
0
Ignore