2009-10-21 84 views
28

我已经看到了随机命名的文件,包括使用C#:什么是生成唯一文件名的最快方法?

System.IO.Path.GetRandomFileName() 

或使用

System.Guid 

和附加文件扩展名的若干建议。

我的问题是:什么是生成唯一文件名的最快方法?

+37

为什么你不使用一种方法*速度够快*? – Joren 2009-10-21 18:14:28

+1

一个很好的问题。答案是,我试图从这个文件系统密集型应用程序中挤出每盎司的性能。 – 2009-10-21 18:17:17

+4

这真的取决于你的意思是“独一无二” - 它是否具有通用的独特性,在文件系统中是独一无二的,在同一个程序的不同线程中是唯一的......? – 2009-10-21 18:17:25

回答

36

GUID将非常快, ,因为它的实施保证Windows可以在100纳秒的时间范围内生成至少16,384个GUIDS 。 (正如其他人指出的那样,规范不能保证,只允许,但是,GUID的生成真的很快,真的)。在任何网络上的任何文件系统上发生冲突的可能性非常低。这是很安全的,尽管最好的做法是始终检查该文件名是否可用,实际上,您甚至不需要这样做。

因此,您只查看除保存本身之外的任何I/O操作,并且在测试机器上测试0.2毫秒以生成名称本身。相当快。

+2

哇!您是否有描述此实施保证的链接源? – 2009-10-21 18:19:27

+7

我不相信Windows gaurantees可以在100 nS中产生** 16,384个GUIDS - 只有通过GUID算法产生的值才能确保具有这种分布级别。此外,使用逻辑,每100-Ns的16k GUIDS将达到每秒1630亿GUIDS ...这意味着它只需要一个CPU周期的1/10来生成一个GUID?这没有多大意义。 – LBushkin 2009-10-21 18:23:31

+0

看到关于GUID唯一性的这个问题http://stackoverflow.com/questions/39771/is-a-guid-unique-100-of-the-time – BlackTigerX 2009-10-21 18:24:13

3

如果您控制文件所在的目标位置,并且只有一个进程和线程写入该文件,只需将一些自动递增数字附加到基本名称即可。

如果您不控制目标,或者需要多线程实现,请使用GUID。

+1

尽管我几乎总是使用GUID来解决这个问题,但LBushkin对于性能是正确的。如果你真的想要*每一滴* perf,递增一个整数并将其转换为一个字符串比生成一个Guid并将其转换为一个字符串更快......但是只有当你拥有目录的控制权时才能工作。 – 2009-10-21 19:02:21

17

你想System.IO.Path.GetTempFileName()

我不能说,其实无论是最快与否,但它是这样做的正确方式,这是更重要的。

+0

+1 - 这是最简单和最好的解决方案。 – Noldorin 2009-10-21 18:32:57

+31

这实际上创建一个文件。我认为你的意思是System.IO.Path.GetRandomFileName() – 2009-10-21 18:46:41

+1

丹是正确的。它在Windows临时目录中创建一个文件。 – adrianbanks 2009-10-21 18:47:38

0

使用一个Int并为每个文件增加它。

+2

OP想要一个唯一的文件名......那么如果一个名为(例如)'“1”'的文件已经存在? – Sree 2017-04-20 13:58:56

-1

类似:

file.MoveTo(deletedfilesdir + @"\" + f.Name + **DateTime.Now.ToFileTimeUtc()** + f.Extension); 
1

如果你控制的目录,你可以基于该lastWriteTime命名文件:

DirectoryInfo info = new DirectoryInfo(directoryPath); 
long uniqueKey = info.LastWriteTime.Ticks+1L; 
string filename = String.Format("file{0}.txt", key); 

但是你要检查这个代码的表演:我想建设一个DirectoryInfo不是免费的。

+0

“建立一个DirectoryInfo不会免费” - 我怀疑你是正确的,特别是如果驱动器/目录不在计算机本地(网络驱动器/ NAS/etc) – 2011-03-23 18:07:58

5

那么我一直在写文件系统驱动程序20年,并会说雷克斯是正确的。生成一个GUID要快得多,因为它比寻找一个唯一的文件名要花费更少的开销。 GetTempFileName实际上创建了一个文件,这意味着它必须调用整个文件系统驱动程序堆栈(谁知道将会有多少个调用并切换到内核模式。)GetRandomFileName听起来更快,但我相信GUID调用甚至更快。人们没有意识到的是,即使测试文件的存在,也需要通过驱动程序堆栈进行完整调用。它实际上导致打开,获取属性并关闭(至少3次调用,具体取决于级别)。实际上,它至少需要20次函数调用并转换到内核模式。 GUIDS对独特性的保证足以满足大多数目的。

我的建议是生成名称并仅在文件不存在时才创建文件。如果是,请抛出异常并捕获它,然后生成一个新的GUID并重试。那样,你没有错误的机会,并且可以在夜晚轻松入睡。

在旁注中,检查错误是如此的过头。如果假设错误,代码应该设计为崩溃,或者捕获异常并处理它。在异常堆栈上更快地推送和弹出地址,而不是每次检查每个函数的错误。

0

我希望这种自我迭代功能可以帮助别人生成一个唯一的文件名。

public string getUniqueFileName(int i, string fullpath, string filename) 
{ 
    string lstDir = fullpath.Substring(0, fullpath.LastIndexOf('\\')); 
    string name = Path.GetFileName(fullpath); 
    string path = fullpath; 

    if (name != filename) 
     path = Path.Combine(lstDir, filename); 

    if (System.IO.File.Exists(path)) 
    { 
     string ext = Path.GetExtension(name); 
     name = Path.GetFileNameWithoutExtension(name);     
     i++; 
     filename = getUniqueFileName(i, fullpath, name + "_" + i + ext); 
    } 

    return filename; 
} 
+0

这不会创建名为'file_1_2_3 '? – user5226582 2018-03-02 11:39:00

+0

虽然这会在路径中生成一个唯一的文件名(虽然它不是线程安全的),但与其他方法相比,它会非常慢,只是简单地生成一个唯一的文件名而不检查它是否已经存在。我想这个操作需要快速生成一个唯一的文件名。 Btw你的答案解决了这个问题,它可能对别人有帮助。 – Perrier 2018-03-02 11:51:02

+0

是的,它的确如此。我的期望是增加相同的数字,但它变成了连接。需要修改代码以使其按预期工作。如果有人更正我的代码,会很感激。提前致谢。 – Bikuz 2018-03-02 11:52:08

相关问题