简体   繁体   English

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

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

I don't necessarily want to use UUIDs since they are fairly long.我不一定要使用 UUID,因为它们相当长。

The file just needs to be unique within its directory.该文件只需要在其目录中是唯一的。

One thought which comes to mind is to use File.createTempFile(String prefix, String suffix) , but that seems wrong because the file is not temporary.想到的一种想法是使用File.createTempFile(String prefix, String suffix) ,但这似乎是错误的,因为该文件不是临时文件。

The case of two files created in the same millisecond needs to be handled.需要处理在同一毫秒内创建两个文件的情况。

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.好吧,您可以使用 3 参数版本: File.createTempFile(String prefix, String suffix, File directory)它将让您将其放在您想要的位置。 Unless you tell it to, Java won't treat it differently than any other file.除非你告诉它,Java 不会将它与任何其他文件区别对待。 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).唯一的缺点是文件名保证至少有 8 个字符长(前缀最少 3 个字符,加上函数生成的 5 个或更多字符)。

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.如果这对你来说太长了,我想你总是可以从文件名“a”开始,然后循环“b”、“c”等,直到找到一个不存在的文件。

I'd use Apache Commons Lang library (我会使用 Apache Commons Lang 库( http://commons.apache.org/lang ). http://commons.apache.org/lang )。

There is a class org.apache.commons.lang.RandomStringUtils that can be used to generate random strings of given length.有一个类org.apache.commons.lang.RandomStringUtils可用于生成给定长度的随机字符串。 Very handy not only for filename generation!不仅对于文件名生成非常方便!

Here is the example:这是示例:

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

I use the timestamp我使用时间戳

ie IE

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

And have the simpleDateFormat initialized to something like as:并将 simpleDateFormat 初始化为如下所示:

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

EDIT编辑

What about关于什么

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

Unless the number of files created in the same second is too high.除非同一秒内创建的文件数量太多。

If that's the case and the name doesn't matters如果是这样的话,名字并不重要

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

:P :P

This works for me:这对我有用:

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

Output filenames should look like :输出文件名应如下所示:

2OoBwH8OwYGKW2QE_4Sep2013061732GMT_1378275452253.Ext

Look at the File javadoc , the method createNewFile will create the file only if it doesn't exist, and will return a boolean to say if the file was created.查看文件 javadoc ,方法 createNewFile 只会在文件不存在时创建文件,并返回一个布尔值来说明文件是否已创建。

You may also use the exists() method:你也可以使用 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);
    //Generating Unique File Name
    public String getFileName() {
        String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date());
        return "PNG_" + timeStamp + "_.png";
    }

If you have access to a database, you can create and use a sequence in the file name.如果您有权访问数据库,则可以在文件名中创建和使用序列。

select mySequence.nextval from dual;

It will be guaranteed to be unique and shouldn't get too large (unless you are pumping out a ton of files).它将保证是唯一的并且不应变得太大(除非您要输出大量文件)。

I use current milliseconds with random numbers我使用随机数的当前毫秒

ie IE

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

Combining other answers, why not use the ms timestamp with a random value appended;结合其他答案,为什么不使用附加随机值的 ms 时间戳; repeat until no conflict, which in practice will be almost never.重复直到没有冲突,这在实践中几乎永远不会发生。

For example: File-ccyymmdd-hhmmss-mmm-rrrrrr.txt例如:文件-ccyymmdd-hhmmss-mmm-rrrrrr.txt

Problem is synchronization.问题是同步。 Separate out regions of conflict.分离出冲突区域。

Name the file as : (server-name)_(thread/process-name)_(millisecond/timestamp).(extension)将文件命名为:( (server-name)_(thread/process-name)_(millisecond/timestamp).(extension)
example : aws1_t1_1447402821007.png示例: aws1_t1_1447402821007.png

为什么不使用基于时间戳的东西..?

This also works这也有效

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

logFileName = "loggerFile_" + logFileName;

I understand that I am too late to reply on this question.我知道我已经来不及回答这个问题了。 But I think I should put this as it seems something different from other solution.但我认为我应该把它放在那里,因为它似乎与其他解决方案有所不同。

We can concatenate threadname and current timeStamp as file name.我们可以连接线程名和当前时间戳作为文件名。 But with this there is one issue like some thread name contains special character like "\\" which can create problem in creating file name.但是这样有一个问题,比如某些线程名称包含特殊字符,如“\\”,这可能会在创建文件名时产生问题。 So we can remove special charater from thread name and then concatenate thread name and time stamp所以我们可以从线程名称中删除特殊字符,然后连接线程名称和时间戳

fileName = threadName(after removing special charater) + currentTimeStamp

Why not use synchronized to process multi thread.为什么不使用synchronized来处理多线程。 here is my solution,It's can generate a short file name , and it's unique.这是我的解决方案,它可以生成一个短文件名,而且它是独一无二的。

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

blew is main function for test , It's work. blew 是 test 的主要功能,它的工作。

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

}

How about generate based on time stamp rounded to the nearest millisecond, or whatever accuracy you need... then use a lock to synchronize access to the function.如何根据四舍五入到最接近毫秒的时间戳或您需要的任何精度生成...然后使用锁来同步对函数的访问。

If you store the last generated file name, you can append sequential letters or further digits to it as needed to make it unique.如果您存储最后生成的文件名,您可以根据需要在其中附加连续的字母或更多数字以使其唯一。

Or if you'd rather do it without locks, use a time step plus a thread ID, and make sure that the function takes longer than a millisecond, or waits so that it does.或者,如果您更愿意在没有锁的情况下执行此操作,请使用时间步长加上线程 ID,并确保该函数花费的时间超过一毫秒,或者等待以使其执行。

It looks like you've got a handful of solutions for creating a unique filename, so I'll leave that alone.看起来您有一些用于创建唯一文件名的解决方案,所以我将不理会它。 I would test the filename this way:我会这样测试文件名:

    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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 有没有一种方法可以用Java生成文件名的8.3或“短”(Windows)版本? - Is there a way to generate the 8.3 or 'short' (Windows) version of a file name in Java? 在java中生成唯一ID的最佳方法 - Best way to generate a unique ID in java 在 Java 中生成唯一随机数的最佳方法 - Best way to generate unique Random number in Java 最佳方式如何生成短名称,例如数据库中的属性值 - How is best way generate a short name e.g value of property in database 在 Java 中生成唯一双精度值的最有效方法是什么 - What is the most efficent way to generate unique double values in Java 为 Selenide+Java 构建独特的 CSS 定位器的最佳方法是什么? - What is the best way to build unique CSS locators for Selenide+Java? 这是在实际软件环境中制作构建器模式的正确方法吗? 简而言之,在 Java 中创建构建器模式的最佳方法是什么 - is this the right way to make builder pattern in real software environment? in short what is the best way to create builder pattern in java 从libvirt Relaxng模式生成Java类的最佳方法是什么? - What is the best way to generate java classes from libvirt relaxng schemas? 在Java中读取文件的最佳方法是什么? - What is the best way to read a file in Java? 用Java写入文件的最佳方法是什么? - What is the best way to write to a file in Java?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM