在Java中生成唯一且短的文件名的最佳方法是什么

在Java中生成唯一且短的文件名的最佳方法是什么,java,file,Java,File,我不一定要使用UUID,因为它们相当长 该文件只需要在其目录中是唯一的 我想到的一个想法是使用File.createTempFile(字符串前缀,字符串后缀),但这似乎是错误的,因为该文件不是临时文件 需要处理在同一毫秒内创建两个文件的情况。为什么不使用基于时间戳的内容?我使用时间戳 i、 e 并将SimpleDataFormat初始化为如下内容: new SimpleDateFormat("File-ddMMyy-hhmmss.SSS.txt"); 编辑 那怎么办 new File(Stri

我不一定要使用UUID,因为它们相当长

该文件只需要在其目录中是唯一的

我想到的一个想法是使用
File.createTempFile(字符串前缀,字符串后缀)
,但这似乎是错误的,因为该文件不是临时文件


需要处理在同一毫秒内创建两个文件的情况。

为什么不使用基于时间戳的内容?

我使用时间戳

i、 e

并将SimpleDataFormat初始化为如下内容:

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

那怎么办

new File(String.format("%s.%s", sdf.format( new Date() ),
                                random.nextInt(9)));
除非在同一秒内创建的文件数量太多

如果是这样的话,名字不重要

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

:p

好吧,您可以使用三参数版本:它可以让您将其放在您想要的地方。除非您告诉它,否则Java不会将其与任何其他文件区别对待。唯一的缺点是文件名长度保证至少为8个字符(前缀至少为3个字符,加上函数生成的5个或更多字符)

如果这对您来说太长,我想您总是可以从文件名“a”开始,循环“b”、“c”等,直到找到一个不存在的文件。

看看,createNewFile方法将仅在文件不存在时创建该文件,并返回一个布尔值来说明文件是否已创建

也可以使用exists()方法:


根据四舍五入到最接近毫秒的时间戳生成,或者根据您需要的精度生成,怎么样。。。然后使用锁同步对函数的访问

如果存储最后生成的文件名,则可以根据需要向其附加顺序字母或其他数字,以使其唯一


或者,如果您希望在不使用锁的情况下执行此操作,请使用时间步长加上线程ID,并确保函数所需时间超过毫秒,或者等待时间超过毫秒。

结合其他答案,为什么不使用附加随机值的ms timestamp;重复,直到没有冲突,这在实践中几乎永远不会发生


例如:File-ccyymmdd-hhmmss-mmm-rrrrrrr.txt

我会使用ApacheCommonsLang库()

有一个类
org.apache.commons.lang.RandomStringUtils
,可用于生成给定长度的随机字符串。非常方便,不仅用于文件名生成

以下是一个例子:

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

如果您有权访问数据库,则可以在文件名中创建并使用序列

select mySequence.nextval from dual;

它将保证是唯一的,并且不应该太大(除非你正在输出大量的文件)。

看起来你已经有了一些创建唯一文件名的解决方案,所以我就不谈了。我将通过以下方式测试文件名:

    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
这对我很有用:

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;
}
//用法:

String newFile;
do{
newFile=generateUniqueFileName() + "." + FileExt;
}
while(new File(basePath+newFile).exists());
输出文件名应如下所示:

2OoBwH8OwYGKW2QE_4Sep2013061732GMT_1378275452253.Ext
这同样有效

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

logFileName = "loggerFile_" + logFileName;

我知道我来不及回答这个问题。但我认为我应该把它放在这里,因为它似乎与其他解决方案有所不同

我们可以将threadname和当前时间戳连接为文件名。但有一个问题是,某些线程名包含特殊字符,如“\”,这会在创建文件名时产生问题。所以我们可以从线程名中删除特殊字符,然后连接线程名和时间戳

fileName = threadName(after removing special charater) + currentTimeStamp

为什么不使用synchronized来处理多线程呢。 这是我的解决方案,它可以生成一个短文件名,并且是唯一的

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'};
这是测试的主要功能,它的工作

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

}
publicstaticvoidmain(字符串[]args){
列表名称=新的ArrayList();
List threads=new ArrayList();
对于(int i=0;i<100;i++){
Thread Thread=新线程(new Runnable(){
@凌驾
公开募捐{
对于(int i=0;i<1000;i++){
字符串名称=generateFileName();
名称。添加(名称);
}
}
});
thread.run();
线程。添加(线程);
}
对于(int i=0;i<10;i++){
试一试{
threads.get(i.join();
}捕捉(中断异常e){
e、 printStackTrace();
}
}
System.out.println(名称);
System.out.println(names.size());
}

问题在于同步。把冲突地区分开

将该文件命名为:
(服务器名称)\ uu(线程/进程名称)\ uu(毫秒/时间戳)。(扩展名)


示例:
aws1\u t1\u 1447402821007.png

我将当前毫秒与随机数一起使用

i、 e


是的,但是如果两个文件是在同一秒内创建的,或者是毫秒。毫秒是不可能的,你可以在它上面设置一个计时器来停止在同一秒内创建文件…@JeffBloom我遇到了一个与你问的问题类似的问题。我正在创建一个文件,文件名中包含System.currentTimeMillis()。假设我复制该文件并使用相同的System.currentTimeMillis()粘贴另一个文件,它将不会读取我的下一个文件。如何不允许用户复制和粘贴具有相同System.currentTimeMillis()的文件。如果在同一毫秒内创建两个文件,将非常感谢任何帮助。如果重试失败,则会显示新的时间戳different@Jeff. 只需检测冲突并重试,直到没有冲突;在实践中,这应该是非常罕见的。如果你无论如何都要检测冲突,只需生成一个随机文件名,而不必担心时间——例如,请参阅我的答案。生成(比如)8个字符的相同文件名的情况仍然非常罕见:)不要太注意名称中的“Temp”部分;阅读javadocs,了解它更多的是关于唯一性,这是临时文件经常需要的。但不一定只是对他们来说。对类似的事情使用锁同步几乎总是一个可怕的想法——互斥锁对pr有好处
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'};
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());

}
    //Generating Unique File Name
    public String getFileName() {
        String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date());
        return "PNG_" + timeStamp + "_.png";
    }
Random random=new Random();
String ext = ".jpeg";
File dir = new File("/home/pregzt");
String name = String.format("%s%s",System.currentTimeMillis(),random.nextInt(100000)+ext);
File file = new File(dir, name);