Cuál es la mejor manera de generar un nombre de archivo único y corto en Java


No necesariamente quiero usar UUID ya que son bastante largos.

El archivo solo necesita ser único dentro de su directorio.

Un pensamiento que viene a la mente es usar File.createTempFile(String prefix, String suffix), pero eso parece incorrecto porque el archivo no es temporal.

El caso de dos archivos creados en el mismo milisegundo necesita ser manejado.

 63
Author: Reddy, 2009-05-05

15 answers

Bueno, podrías usar la versión de 3 argumentos: File.createTempFile(String prefix, String suffix, File directory) lo que te permitirá ponerlo donde quieras. A menos que se lo diga, Java no lo tratará de manera diferente a cualquier otro archivo. El único inconveniente es que se garantiza que el nombre del archivo tenga al menos 8 caracteres de largo (mínimo de 3 caracteres para el sufijo, más 5 o más caracteres generados por la función).

Si eso es demasiado largo para usted, supongo que siempre podría comenzar con el nombre de archivo "a" , y recorrer "b", " c", etc. hasta que encuentres uno que no exista ya.

 77
Author: Pesto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:22:00

Usaría la biblioteca Apache Commons Lang (http://commons.apache.org/lang).

Hay una clase org.apache.commons.lang.RandomStringUtils que se puede usar para generar cadenas aleatorias de una longitud determinada. Muy útil no solo para la generación de nombres de archivo!

Aquí está el ejemplo:

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);
 25
Author: Tomasz Błachowicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:51:46

Uso la marca de tiempo

Es decir

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

Y tener el SimpleDateFormat inicializado a algo como as:

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

EDITAR

¿Qué pasa con

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

A menos que el número de archivos creados en el mismo segundo sea demasiado alto.

Si ese es el caso y el nombre no importa

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

: P

 11
Author: OscarRyz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:32:11

Esto funciona para mí:

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

Los nombres de los archivos de salida deberían tener el siguiente aspecto:

2OoBwH8OwYGKW2QE_4Sep2013061732GMT_1378275452253.Ext
 10
Author: MD. Mohiuddin Ahmed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-20 08:26:54

Si tiene acceso a una base de datos, puede crear y utilizar una secuencia en el nombre del archivo.

select mySequence.nextval from dual;

Se garantizará que sea único y no debería ser demasiado grande (a menos que esté bombeando una tonelada de archivos).

 5
Author: Shane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:52:16

Mira el archivo javadoc, el método createNewFile creará el archivo solo si no existe, y devolverá un booleano para decir si el archivo fue creado.

También puedes usar el método exists ():

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
Author: pgras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-20 20:15:48

¿por Qué no usar algo basado en una marca de tiempo..?

 2
Author: Galwegian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:16:25

Combinando otras respuestas, por qué no usar la marca de tiempo ms con un valor aleatorio agregado; repita hasta que no haya conflicto, que en la práctica será casi nunca.

Por ejemplo: File-ccyymmdd-hhmmss-mmm-rrrrr.txt

 2
Author: Lawrence Dol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-06 01:47:19

Qué tal generar basado en la marca de tiempo redondeada al milisegundo más cercano, o cualquier precisión que necesite... a continuación, utilice un bloqueo para sincronizar el acceso a la función.

Si almacena el último nombre de archivo generado, puede agregarle letras secuenciales o dígitos adicionales según sea necesario para que sea único.

O si prefiere hacerlo sin bloqueos, use un paso de tiempo más un ID de hilo, y asegúrese de que la función tarda más de un milisegundo, o espera para que lo haga.

 0
Author: justinhj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 16:31:17

Parece que tienes un puñado de soluciones para crear un nombre de archivo único, así que dejaré eso en paz. Probaría el nombre del archivo de esta manera:

    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
Author: Peter Anthony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-05 18:14:41

Esto también funciona

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

logFileName = "loggerFile_" + logFileName;
 0
Author: T.Akshay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-05 10:01:57

Entiendo que es demasiado tarde para responder a esta pregunta. Pero creo que debería poner esto, ya que parece algo diferente de otra solución.

Podemos concatenar threadname y timeStamp actual como nombre de archivo. Pero con esto hay un problema como algún nombre de hilo contiene carácter especial como " \ " que puede crear un problema en la creación de nombre de archivo. Así que podemos eliminar el personaje especial del nombre del hilo y luego concatenar el nombre del hilo y la marca de tiempo

fileName = threadName(after removing special charater) + currentTimeStamp
 0
Author: Roshan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-10 08:47:03

¿Por qué no usar sincronizado para procesar subprocesos múltiples? aquí está mi solución, puede generar un nombre de archivo corto, y es único.

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'};

Sopló es la función principal para la prueba, es trabajo.

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
Author: Ignore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-12 04:05:49

El problema es la sincronización. Separar las regiones de conflicto.

Nombre el archivo como: (server-name)_(thread/process-name)_(millisecond/timestamp).(extension)
ejemplo: aws1_t1_1447402821007.png

 0
Author: smit thakkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-20 15:35:10
    //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
Author: LEGEND MORTAL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-09 19:19:50