在Java中生成一个唯一的短文件名的最好方法是什么?
我不一定要使用UUID,因为它们相当长。
该文件只需要在其目录中是唯一的。
想到的一个想法是使用File.createTempFile(String prefix, String suffix)
,但这似乎是错误的,因为该文件不是临时的。
需要处理在同一个毫秒内创build的两个文件的情况。
那么,你可以使用3参数版本: File.createTempFile(String prefix, String suffix, File directory)
,这将让你把它放在你想要的地方。 除非你告诉它,否则Java不会以任何其他文件的方式对待它。 唯一的缺点是文件名至less保证8个字符(后缀最less3个字符,加上5个或更多字符)。
如果这对你来说太长了,我想你总是可以从文件名“a”开始,然后循环“b”,“c”等,直到find一个不存在的文件。
我会使用Apache Commons Lang库( http://commons.apache.org/lang )。
有一个类org.apache.commons.lang.RandomStringUtils
可以用来生成给定长度的随机string。 非常方便,不仅适用于文件名生成!
这是一个例子:
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);
我使用时间戳
即
new File( simpleDateFormat.format( new Date() ) );
并将simpleDateFormat初始化为如下所示:
new SimpleDateFormat("File-ddMMyy-hhmmss.SSS.txt");
编辑
关于什么
new File(String.format("%s.%s", sdf.format( new Date() ), random.nextInt(9)));
除非在同一秒内创build的文件数量太高。
如果是这样的话,名字不重要
new File( "file."+count++ );
:P
这适用于我:
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());
输出文件名应该如下所示:
2OoBwH8OwYGKW2QE_4Sep2013061732GMT_1378275452253.Ext
看一下文件javadoc ,createNewFile方法只会在文件不存在的情况下创build文件,并返回一个布尔值来表示文件是否被创build。
你也可以使用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);
如果您有权访问数据库,则可以在文件名中创build和使用序列。
select mySequence.nextval from dual;
它将被保证是唯一的,不应该太大(除非你抽出大量的文件)。
为什么不只是使用基于时间戳的东西..?
结合其他答案,为什么不使用带有随机值的ms时间戳; 重复,直到没有冲突,这实际上将永远不会。
例如:File-ccyymmdd -hhmmss-mmm-rrrrrr.txt
如何生成基于时间戳四舍五入到最接近的毫秒,或者你需要什么精度…然后使用锁来同步访问function。
如果存储最后生成的文件名,则可以根据需要附加连续字母或更多数字以使其唯一。
或者,如果你宁愿不加锁,使用一个时间步加一个线程ID,并确保该函数花费的时间超过一毫秒,或等待,以便它。
看起来你已经有了一些解决scheme来创build一个独特的文件名,所以我会一个人留下。 我会这样testing文件名:
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 logFileName = new SimpleDateFormat("yyyyMMddHHmm'.txt'").format(new Date()); logFileName = "loggerFile_" + logFileName;
我明白现在回答这个问题为时已晚。 但我想我应该把这个看起来和其他解决scheme有所不同。
我们可以连接线程名和当前时间戳作为文件名。 但是有了这样一个问题,像一些线程名称包含像“\”这样的特殊字符,可以在创build文件名时产生问题。 因此,我们可以从线程名称中删除特殊字符,然后连接线程名称和时间戳
fileName = threadName(after removing special charater) + currentTimeStamp
为什么不使用synchronized来处理multithreading。 这里是我的解决scheme,它可以生成一个简短的文件名,并且是唯一的。
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'};
吹是testing的主要function,是工作。
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()); }