如何使用 .NET 创建具有特定扩展名的临时文件?
-
06-09-2019 - |
题
我需要生成一个扩展名为 .csv 的唯一临时文件。
我现在做的是
string filename = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv");
但是,这并不能保证我的 .csv 文件是唯一的。
我知道发生冲突的可能性非常低(特别是如果您认为我没有删除 .tmp 文件),但这段代码对我来说看起来不太好。
当然,我可以手动生成随机文件名,直到我最终找到一个唯一的文件名(这不应该成为问题),但我很想知道其他人是否找到了解决此问题的好方法。
解决方案
保证是(统计)唯一的:
string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
(要从wiki文章引用在碰撞的probabilty:
...一个年度的被击中的风险 陨石被估计为一个 机会在17个十亿[19],该装置 概率约为0.00000000006 (6×10-11),相当于赔率 创造一个几十万亿 在的UUID一年有一个 重复。换句话说,只有后 一点产生十亿每天的UUID 第二个在未来100年里, 创建只是一个概率 重复会约50%。该 一个重复的概率会 如果大约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和创建它是非常非常低的机会。这是相当安全的假设,这将是独一无二的。
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()产生的碰撞的情况下;
您也可以替代地使用 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扩展,但你可以指定任何你想要的。我还设置保持标志为true,以便在临时文件使用后保持周围。不幸的是,TempFileCollection每创建一个扩展随机文件。如果您需要更多的临时文件,你可以创建TempFileCollection的多个实例。
为什么不检查文件是否存在?
string fileName;
do
{
fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
} while (System.IO.File.Exists(fileName));
有 C ++的GetTempFileName MSDN文档讨论了您的关注和答案它:
GetTempFileName不能保证文件名是唯一
只有uUnique参数的低16位被使用。这限制GetTempFileName为最多65535唯一的文件名,如果lpPathName和lpPrefixString参数保持相同。
由于用于生成文件名的算法,可以GetTempFileName很差具有相同前缀创建大量文件时执行。在这种情况下,建议您构造基于GUID的唯一文件名
如何:
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");
在我看来,这里提出的大多数答案都是次优的。最接近的一个是布莱恩最初提出的最初的一个。
临时文件名必须是
- 独特的
- 无冲突(尚不存在)
- 原子(在同一操作中创建名称和文件)
- 很难猜测
由于这些要求,您自己编写这样一个野兽并不是一个好主意。编写 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);
在C#简单的函数:
public static string GetTempFileName(string extension = "csv")
{
return Path.ChangeExtension(Path.GetTempFileName(), extension);
}
这可能是得心应手,为您...这是创建一个临时。文件夹并返回它作为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";
这是产生增量文件名一个简单而有效的方法。它看起来在当前直接(你可以随便点是其他地方)并搜索与基地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;
}
根据我从互联网上找到的答案,我的代码如下:
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 指出 在应用程序中使用临时文件:
每当需要临时存储信息以供以后检索时,您应该使用临时文件。
您必须记住的一件事是在终止其创建的应用程序之前删除此临时文件。
如果未删除,它将保留在用户的临时目录中,直到用户手动删除它为止。
我想你应该试试这个:
string path = Path.GetRandomFileName();
path = Path.Combine(@"c:\temp", path);
path = Path.ChangeExtension(path, ".tmp");
File.Create(path);
它生成一个唯一的文件名,并在指定的位置创建与该文件名的文件。