如何创build一个具有特定扩展名的.NET文件?

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

我现在所做的是

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

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

我知道碰撞的几率非常低(特别是如果你考虑到我不删除.tmp文件),但是这段代码对我来说并不好看。

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

保证(统计)独特:

 string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv"; 

(从维基文章中引用碰撞概率:

一个被陨石撞击的年度风险估计是170亿[19]中的一个机会,这意味着概率大概是0.00000000006(6×10-11),相当于创造几十个一年中有数万亿UUID,并有一个副本。 换句话说,在未来100年内每秒产生10亿个UUID之后,创build一个副本的可能性大约为50%。 如果地球上每个人拥有6亿个UUID,一个重复的可能性大约是50%

编辑:也请参阅JaredPar的评论。

试试这个function…

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

它将返回一个完整的path与您select的扩展名。

注意,不能保证生成一个唯一的文件名,因为其他人在技术上可能已经创build了该文件。 然而,有人猜测你的应用程序产生的下一个guid并创build它的可能性非常低。 假设这将是唯一的,这是相当安全的。

 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。 创build一个空文件来保留文件名。 如果Path.GetRandomFileName()产生冲突,它会进行10次尝试;

您也可以使用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为每个扩展创build一个随机文件。 如果您需要更多的临时文件,您可以创buildTempFileCollection的多个实例。

C ++的GetTempFileName的MSDN文档讨论了您的疑虑并回答了它:

GetTempFileName不能保证文件名是唯一的

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

由于用于生成文件名的algorithm,当创build具有相同前缀的大量文件时,GetTempFileName可能performance不佳。 在这种情况下, build议您根据GUID构build唯一的文件名

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

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

怎么样:

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

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

您也可以执行以下操作

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

这也如预期般运作

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

这可能对你很方便…这是创build一个临时工。 文件夹并将其作为VB.NET中的string返回。

轻松转换为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 

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

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

临时文件名必须是

  • 独特
  • 无冲突(不存在)
  • primefaces(在同一操作中创build名称和文件)
  • 很难猜测

由于这些要求,自己编写这样一个野兽并不是一个好主意。 智能人员编写IO库担心像locking(如果需要)等东西。因此,我看到没有必要重写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 tStamp = String.Format(“{0:yyyyMMdd.HHmmss}”,DateTime.Now);
stringProcID = Process.GetCurrentProcess()。Id.ToString();
stringtmpFolder = System.IO.Path.GetTempPath();
stringoutFile = tmpFolder + ProcID +“_”+ tStamp +“.txt”;

我想你应该试试这个:

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

它会生成一个唯一的文件名并在指定位置创build一个具有该文件名的文件。