如何创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一个具有该文件名的文件。