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

我现在做的是

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

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

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

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


当前回答

public static string GetTempFileName(string extension)
{
  int attempt = 0;
  while (true)
  {
    string fileName = Path.GetRandomFileName();
    fileName = Path.ChangeExtension(fileName, extension);
    fileName = Path.Combine(Path.GetTempPath(), fileName);

    try
    {
      using (new FileStream(fileName, FileMode.CreateNew)) { }
      return fileName;
    }
    catch (IOException ex)
    {
      if (++attempt == 10)
        throw new IOException("No unique temporary file name is available.", ex);
    }
  }
}

注意:这类似于Path.GetTempFileName。创建一个空文件以保留文件名。它会尝试10次,以防Path.GetRandomFileName()生成的冲突;

其他回答

在这里,我们可以首先找到文件的扩展名 它来自于文件,在找到扩展名之后。然后,我们 可以创建文件的临时名称,之后我们可以改变 扩展前一个,它将工作。

var name = Path.GetTempFileName();
var changename = Path.GetFileName(name);
var fileName = Path.ChangeExtension(changename, fileExtension);

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

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

你也可以选择使用System.CodeDom.Compiler.TempFileCollection。

string tempDirectory = @"c:\\temp";
TempFileCollection coll = new TempFileCollection(tempDirectory, true);
string filename = coll.AddExtension("txt", true);
File.WriteAllText(Path.Combine(tempDirectory,filename),"Hello World");

这里我使用txt扩展名,但你可以指定任何你想要的。我还将keep标志设置为true,以便在使用后保留临时文件。不幸的是,TempFileCollection为每个扩展名创建一个随机文件。如果需要更多临时文件,可以创建TempFileCollection的多个实例。

这就是我所做的:

string tStamp = String.Format("{0:yyyyMMdd.HHmmss}", DateTime.Now);
string ProcID = Process.GetCurrentProcess().Id.ToString();
string tmpFolder = System.IO.Path.GetTempPath();
string outFile = tmpFolder + ProcID + "_" + tStamp + ".txt";

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

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