我需要用.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);

其他回答

这是生成增量文件名的一种简单但有效的方法。它将直接查看当前文件(您可以轻松地将其指向其他地方),并搜索以YourApplicationName*.txt为基础的文件(同样,您可以轻松地更改该文件)。它将从0000开始,因此第一个文件名将是YourApplicationName0000.txt。如果由于某种原因,文件名在左右部分之间(即不是数字)有垃圾,那么这些文件将通过tryparse调用被忽略。

    public static string CreateNewOutPutFile()
    {
        const string RemoveLeft = "YourApplicationName";
        const string RemoveRight = ".txt";
        const string searchString = RemoveLeft + "*" + RemoveRight;
        const string numberSpecifier = "0000";

        int maxTempNdx = -1;

        string fileName;
        string [] Files = Directory.GetFiles(Directory.GetCurrentDirectory(), searchString);
        foreach( string file in Files)
        {
            fileName = Path.GetFileName(file);
            string stripped = fileName.Remove(fileName.Length - RemoveRight.Length, RemoveRight.Length).Remove(0, RemoveLeft.Length);
            if( int.TryParse(stripped,out int current) )
            {
                if (current > maxTempNdx)
                    maxTempNdx = current;
            }
        }
        maxTempNdx++;
        fileName = RemoveLeft + maxTempNdx.ToString(numberSpecifier) + RemoveRight;
        File.CreateText(fileName); // optional
        return fileName;
    }

这对你来说可能很方便…它是创建一个temp。文件夹并在VB.NET中以字符串的形式返回。

易于转换为c#:

Public Function GetTempDirectory() As String
    Dim mpath As String
    Do
        mpath = System.IO.Path.Combine(System.IO.Path.GetTempPath, System.IO.Path.GetRandomFileName)
    Loop While System.IO.Directory.Exists(mpath) Or System.IO.File.Exists(mpath)
    System.IO.Directory.CreateDirectory(mpath)
    Return mpath
End Function

这对我来说似乎工作得很好:它检查文件是否存在,并创建文件以确保它是一个可写的位置。 应该可以正常工作,你可以将其更改为直接返回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

这就是我所做的:

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";

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