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

我现在做的是

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

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

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

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


当前回答

试试这个功能…

public static string GetTempFilePathWithExtension(string extension) {
  var path = Path.GetTempPath();
  var fileName = Path.ChangeExtension(Guid.NewGuid().ToString(), extension);
  return Path.Combine(path, fileName);
}

它将返回一个完整的路径和您选择的扩展名。

注意,它不能保证产生唯一的文件名,因为从技术上讲,其他人可能已经创建了该文件。然而,有人猜出你的应用产生的下一个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 filepath = Path.ChangeExtension(Path.GetTempFileName(), ".csv");

这也符合预期

string filepath = Path.ChangeExtension(Path.GetTempPath() + Guid.NewGuid().ToString(), ".csv");
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()生成的冲突;

在我看来,这里提出的大多数答案都是次优的。最接近的是最初由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);

这对我来说似乎工作得很好:它检查文件是否存在,并创建文件以确保它是一个可写的位置。 应该可以正常工作,你可以将其更改为直接返回FileStream(这通常是临时文件所需要的):

private string GetTempFile(string fileExtension)
{
  string temp = System.IO.Path.GetTempPath();
  string res = string.Empty;
  while (true) {
    res = string.Format("{0}.{1}", Guid.NewGuid().ToString(), fileExtension);
    res = System.IO.Path.Combine(temp, res);
    if (!System.IO.File.Exists(res)) {
      try {
        System.IO.FileStream s = System.IO.File.Create(res);
        s.Close();
        break;
      }
      catch (Exception) {

      }
    }
  }
  return res;
} // GetTempFile