我需要用.csv扩展名生成一个唯一的临时文件。

我现在做的是

string filepath = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv");

但是,这并不能保证.csv文件是唯一的。

我知道发生碰撞的可能性非常低(特别是如果您考虑到我没有删除.tmp文件的话),但是这段代码对我来说不太好。

当然,我可以手动生成随机文件名,直到我最终找到一个唯一的文件名(这应该不是问题),但我很想知道其他人是否已经找到了处理这个问题的好方法。


当前回答

在我看来,这里提出的大多数答案都是次优的。最接近的是最初由Brann提出的。

临时文件名必须是

独特的 无冲突(不存在) 原子(在同一操作中创建名称和文件) 很难猜测

由于这些需求,独自编写这样一个野兽并不是一个好主意。聪明的人写IO库时会担心像锁(如果需要的话)等事情。 因此,我认为没有必要重写System.IO.Path.GetTempFileName()。

这个,即使看起来很笨拙,也应该做到:

//Note that this already *creates* the file
string filename1 = System.IO.Path.GetTempFileName()
// Rename and move
filename = filename.Replace(".tmp", ".csv");
File.Move(filename1 , filename);

其他回答

为什么不检查文件是否存在?

string fileName;
do
{
    fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
} while (System.IO.File.Exists(fileName));

您还可以执行以下操作

string filepath = Path.ChangeExtension(Path.GetTempFileName(), ".csv");

这也符合预期

string filepath = Path.ChangeExtension(Path.GetTempPath() + Guid.NewGuid().ToString(), ".csv");

c++的GetTempFileName的MSDN文档讨论了你的问题并回答了它:

GetTempFileName不能保证文件名是唯一的。 只使用uUnique参数的下16位。如果lpPathName和lpPrefixString参数保持不变,这将限制GetTempFileName最多为65,535个唯一的文件名。 由于用于生成文件名的算法,当使用相同的前缀创建大量文件时,GetTempFileName的性能可能很差。在这种情况下,建议您基于guid构造惟一的文件名。

我认为你应该试试这个:

string path = Path.GetRandomFileName();
path = Path.Combine(@"c:\temp", path);
path = Path.ChangeExtension(path, ".tmp");
File.Create(path);

它生成一个唯一的文件名,并在指定位置用该文件名创建一个文件。

如何:

Path.Combine(Path.GetTempPath(), DateTime.Now.Ticks.ToString() + "_" + Guid.NewGuid().ToString() + ".csv")

计算机在同一时刻生成相同的Guid是极不可能的。我在这里看到的唯一缺点是DateTime.Now.Ticks会增加性能影响。