C# 如何使用.NET创建具有特定扩展名的临时文件?

C# 如何使用.NET创建具有特定扩展名的临时文件?,c#,.net,temporary-files,C#,.net,Temporary Files,我需要生成一个扩展名为.csv的唯一临时文件 我现在做的是 string filename = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv"); 但是,这并不能保证我的.csv文件是唯一的 我知道我碰过的几率很低(特别是如果你认为我不删除.tMP文件),但是这个代码对我来说不太好。 当然,我可以手动生成随机文件名,直到最终找到唯一的文件名(这应该不是问题),但我很想知道其他人是否找到了处理此问题的好方法。保证(统计上)唯一: (

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

我现在做的是

string filename = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv");
但是,这并不能保证我的.csv文件是唯一的

我知道我碰过的几率很低(特别是如果你认为我不删除.tMP文件),但是这个代码对我来说不太好。 当然,我可以手动生成随机文件名,直到最终找到唯一的文件名(这应该不是问题),但我很想知道其他人是否找到了处理此问题的好方法。

保证(统计上)唯一:

(引用维基上关于碰撞概率的文章:

…一个人每年有可能被 据估计,陨石是其中之一 170亿[19]中的机会,这意味着 概率约为0.00000000006 (6 × 10−11) ,相当于 创造数十万亿美元 UUID在一年内有一个 重复。换句话说,只有在 每年产生10亿个UUID 在接下来的100年中,第二个 仅创建一个的概率 复制品大约是50% 一次重复的可能性是 如果地球上的每个人 拥有6亿个UUID

编辑:请参阅JaredPar的评论。

试试这个功能

public static string GetTempFilePathWithExtension(string extension) {
  var path = Path.GetTempPath();
  var fileName = Guid.NewGuid().ToString() + extension;
  return Path.Combine(path, fileName);
}
它将返回一个包含您选择的扩展名的完整路径


注意,不能保证生成唯一的文件名,因为技术上其他人可能已经创建了该文件。但是,有人猜测您的应用程序生成的下一个guid并创建该guid的可能性非常低。可以很安全地假设该guid是唯一的。

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

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

您还可以执行以下操作

string filename = Path.ChangeExtension(Path.GetTempFileName(), ".csv");
这也和预期的一样有效

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

您也可以选择使用

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

如何:

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

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

这就是我正在做的:

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 tStamp=string.Format(“{0:yyyyMMdd.HHmmss}”,DateTime.Now); 字符串ProcID=Process.GetCurrentProcess().Id.ToString(); 字符串tmpFolder=System.IO.Path.GetTempPath(); 字符串输出文件=tmpFolder+ProcID+“”+tStamp+”.txt”;
这对你来说可能很方便…它是创建一个临时文件夹并在VB.NET中以字符串形式返回

可轻松转换为C#:


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


我想你应该试试这个:

string path = Path.GetRandomFileName();
path = Path.Combine(@"c:\temp", path);
path = Path.ChangeExtension(path, ".tmp");
File.Create(path);
它生成一个唯一的文件名,并在指定位置创建一个具有该文件名的文件

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类似。将创建一个空文件以保留文件名。如果Path.GetRandomFileName()产生冲突,它将尝试10次;

的MSDN文档将讨论您的问题并回答:

GetTempFileName无法保证文件名是唯一的

仅使用uUnique参数的较低16位。如果lpPathName和lpPrefixString参数保持不变,则这将GetTempFileName限制为最多65535个唯一文件名

由于用于生成文件名的算法,当创建大量具有相同前缀的文件时,GetTempFileName的性能可能会很差。在这种情况下,建议您基于GUID构建唯一的文件名


在我看来,这里提出的大多数答案都是次优的。最接近的答案是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;
    }
C#中的简单函数:


根据我在互联网上找到的答案,我的代码如下:

public static string GetTemporaryFileName()
{       
    string tempFilePath = Path.Combine(Path.GetTempPath(), "SnapshotTemp");
    Directory.Delete(tempFilePath, true);
    Directory.CreateDirectory(tempFilePath);
    return Path.Combine(tempFilePath, DateTime.Now.ToString("MMddHHmm") + "-" + Guid.NewGuid().ToString() + ".png");
}
正如杰伊·希尔亚德(Jay Hilyard)的C#Cookbook,斯蒂芬·泰尔赫特(Stephen Teilhet)指出:

  • 无论何时需要存储,都应该使用临时文件 信息暂时保存,以便以后检索

  • 你必须记住的一件事是删除这个临时文件 在创建它的应用程序终止之前

  • 如果未删除,它将保留在用户的临时文件夹中 目录,直到用户手动删除它

我混合了答案,记住我想要GetTempFileName方法的语义(文件名是创建的新文件的名称)添加首选扩展名

string GetNewTempFile(string extension)
{
    if (!extension.StartWith(".")) extension="." + extension;
    string fileName;
    bool bCollisions = false;
    do {
        fileName = Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString() + extension);
        try
        {
            using (new FileStream(fileName, FileMode.CreateNew)) { }
            bCollisions = false;
        }
        catch (IOException)
        {
            bCollisions = true;
        }
    }
    while (bCollisions);
    return fileName;
}

但不保证位于可写位置,也不保证
//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);
    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;
    }
public static string GetTempFileName(string extension = "csv")
{
    return Path.ChangeExtension(Path.GetTempFileName(), extension);
}
public static string GetTemporaryFileName()
{       
    string tempFilePath = Path.Combine(Path.GetTempPath(), "SnapshotTemp");
    Directory.Delete(tempFilePath, true);
    Directory.CreateDirectory(tempFilePath);
    return Path.Combine(tempFilePath, DateTime.Now.ToString("MMddHHmm") + "-" + Guid.NewGuid().ToString() + ".png");
}
string GetNewTempFile(string extension)
{
    if (!extension.StartWith(".")) extension="." + extension;
    string fileName;
    bool bCollisions = false;
    do {
        fileName = Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString() + extension);
        try
        {
            using (new FileStream(fileName, FileMode.CreateNew)) { }
            bCollisions = false;
        }
        catch (IOException)
        {
            bCollisions = true;
        }
    }
    while (bCollisions);
    return fileName;
}