C#:生成唯一文件名的最快方法是什么?

时间:2009-10-21 18:12:26

标签: c# .net windows performance filesystems

我已经看到了一些关于随机命名文件的建议,包括使用

System.IO.Path.GetRandomFileName()

或使用

System.Guid

并附加文件扩展名。

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

8 个答案:

答案 0 :(得分:36)

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

所以你看除了保存本身之外没有I / O操作,并且< 0.2毫秒(在测试机器上)生成名称本身。很快。

答案 1 :(得分:16)

您想要System.IO.Path.GetTempFileName()

我实际上无法确定它是否最快,但这是正确的方式,这更为重要。

答案 2 :(得分:5)

好吧,我已经编写了20年的文件系统驱动程序,并且会说Rex是正确的。生成guid要快得多,因为它比搜索唯一文件名所需的开销要少得多。 GetTempFileName实际上创建了一个文件,这意味着它必须通过整个文件系统驱动程序堆栈调用(谁知道将调用多少次调用并切换到内核模式。)GetRandomFileName听起来更快,但我相信GUID调用更快。人们没有意识到的是,即使测试文件的存在,也需要通过驱动程序堆栈进行完整的调用。它实际上导致open,get属性和close(至少有3个调用,具体取决于级别)。实际上,它至少需要20个函数调用并转换到内核模式。 GUIDS保证其独特性足以满足大多数目的。

我的建议是生成名称并仅在文件不存在时创建文件。如果是,抛出异常并捕获它,然后生成一个新的guid并再试一次。这样,你就没有错误的机会,晚上可以轻松入睡。

另一方面,检查错误是如此过度。如果假设错误,代码应设计成崩溃,或者捕获异常并处理它。它在异常堆栈上的推送和弹出以及地址要快得多,而不是每次检查每个函数的错误。

答案 3 :(得分:3)

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

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

答案 4 :(得分:1)

如果您控制目录,则可以根据lastWriteTime命名文件:

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

但是你必须检查这段代码的性能:我想构建一个DirectoryInfo并不是免费的。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

您可以执行以下操作:

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

答案 7 :(得分: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;
}