我需要生成一个扩展名为.csv的唯一临时文件。
我现在做的是
string filename = System.IO.Path.GetTempFileName().Replace(".tmp", ".csv");
但是,这并不能保证我的.csv文件是唯一的。
我知道我遇到碰撞的可能性非常低(特别是如果你认为我没有删除.tmp文件),但这段代码看起来不太好。
当然我可以手动生成随机文件名,直到我最终找到一个独特的文件名(这应该不是问题),但我很想知道其他人是否找到了处理这个问题的好方法。 / p>
答案 0 :(得分:320)
保证(统计上)独特:
string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
(引自维基文章关于碰撞的可能性:
编辑:请同时查看JaredPar的评论。......每年遭受一次袭击的风险 陨石估计是一个 机会在170亿[19],这意味着 概率约为0.00000000006 (6×10-11),相当于赔率 创造了几十万亿 UUID在一年内有一个 重复。换句话说,只有在之后 每个产生10亿UUID 第二个是未来100年 创造一个的概率 重复约为50%。该 一个重复的概率是 如果地球上每个人都约50% 拥有6亿UUID
答案 1 :(得分:51)
试试这个功能......
public static string GetTempFilePathWithExtension(string extension) {
var path = Path.GetTempPath();
var fileName = Guid.NewGuid().ToString() + extension;
return Path.Combine(path, fileName);
}
它将返回一个包含您选择的扩展名的完整路径。
注意,不能保证生成唯一的文件名,因为其他人可能已经在技术上已经创建了该文件。然而,有人猜测你的应用程序产生的下一个guid并创建它的可能性非常低。假设这将是独一无二的,这是非常安全的。
答案 2 :(得分:40)
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次尝试答案 3 :(得分:18)
您也可以使用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为每个扩展创建一个随机文件。如果需要更多临时文件,可以创建多个TempFileCollection实例。
答案 4 :(得分:8)
为什么不检查文件是否存在?
string fileName;
do
{
fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".csv";
} while (System.IO.File.Exists(fileName));
答案 5 :(得分:8)
C++'s GetTempFileName的MSDN文档讨论了您的问题并对其进行了解答:
GetTempFileName无法保证文件名是唯一的。
仅使用uUnique参数的低16位。如果lpPathName和lpPrefixString参数保持不变,这会将GetTempFileName限制为最多65,535个唯一文件名。
由于用于生成文件名的算法,GetTempFileName在创建具有相同前缀的大量文件时可能表现不佳。在这种情况下,建议您根据GUID构建唯一的文件名。
答案 6 :(得分:6)
怎么样:
Path.Combine(Path.GetTempPath(), DateTime.Now.Ticks.ToString() + "_" + Guid.NewGuid().ToString() + ".csv")
计算机在同一时刻生成相同的Guid是极不可能的。我在这里看到的唯一弱点是性能影响DateTime.Now.Ticks将添加。
答案 7 :(得分:5)
您还可以执行以下操作
string filename = Path.ChangeExtension(Path.GetTempFileName(), ".csv");
这也可以按预期工作
string filename = Path.ChangeExtension(Path.GetTempPath() + Guid.NewGuid().ToString(), ".csv");
答案 8 :(得分:3)
C#中的简易功能:
public static string GetTempFileName(string extension = "csv")
{
return Path.ChangeExtension(Path.GetTempFileName(), extension);
}
答案 9 :(得分:3)
在我看来,这里提出的大多数答案都是次优的。最接近的是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);
答案 10 :(得分:2)
这似乎对我来说很好:它检查文件存在并创建文件以确保它是可写的位置。 应该可以正常工作,你可以改变它直接返回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
答案 11 :(得分:2)
这对你来说很方便......这是创造一个临时的。文件夹并将其作为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
答案 12 :(得分:1)
请记住我混合了@Maxence和@Mitch Wheat的答案,我想使用GetTempFileName方法的语义(fileName是创建的新文件的名称),并添加扩展名。
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;
}
答案 13 :(得分:0)
这是一种生成增量文件名的简单但有效的方法。它将直接查看当前内容(您可以轻松指向其他位置)并使用基础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;
}
答案 14 :(得分:0)
这就是我在做的事情:
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";
答案 15 :(得分:0)
根据我在互联网上找到的答案,我将代码显示如下:
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)在Using a Temporary File in Your Application中指出:
无论何时需要存储,都应使用一个临时文件 信息暂时供以后检索。
您必须记住的一件事是删除此临时文件 在创建它的应用程序终止之前。
如果未删除,它将保留在用户的临时目录中 目录,直到用户手动将其删除为止。
答案 16 :(得分:-2)
我想你应该试试这个:
string path = Path.GetRandomFileName();
path = Path.Combine(@"c:\temp", path);
path = Path.ChangeExtension(path, ".tmp");
File.Create(path);
它会生成一个唯一的文件名,并在指定位置创建一个具有该文件名的文件。