当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何使用.NET创建具有特定扩展名的临时文件?》经验,为你挑选了8个好方法。

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

我现在做的是

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

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

我知道我遇到碰撞的可能性非常低(特别是如果你认为我没有删除.tmp文件),但这段代码对我来说并不好看.

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



1> Mitch Wheat..:

保证(统计上)唯一:

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

(引用维基文章中有关碰撞的可能性:

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

编辑:另请参阅JaredPar的评论.


善良的领主们,努力保持头脑远离云层.方法是:生成随机文件名,如果不存在则创建它.所以请帮助他很好地编码.所有这些关于伪随机生成器和普遍唯一数字的讨论都是完全没有必要的.
并且它们不会保证是独一无二的,只是在统计上不太可能.
但不能保证在可写的位置
@Pax:你有更多的机会赢得彩票连续1000次,而不是产生两个想法的指导.我觉得这很独特......
@Mitch它不是唯一的原因是因为它可能*我只需在同一路径中创建一个具有相同名称的文件.保证唯一的GUID也是可预测的,这意味着如果给出足够的信息,我可以猜出你的盒子生成的下一组guid
Path.Combine更好,我甚至可能使用changeExtension Path.ChangeExtension(Path.Combine(System.IO.Path.GetTempPath(),Guid.NewGuid().ToString()),"csv");
需要更多`Path.Combine()`
System.IO.Path.GetTempPath()+ Guid.NewGuid().ToString()+".csvv"将起作用.@Mitch:在我将其标记为已接受之前,您能否更新您的答案?谢谢.
不,米奇,它要么保证,要么不保证.在这种情况下,它不是.我连续1000次(或一百万)赢得彩票的概率不是零.
@Pax:当你连续产生2时让我知道:我认为估计是宇宙的年龄......
@Mitch(续)这样我可以在返回GUID之前创建一个具有相同名称的文件.处理文件系统时,保证很少.我认为这是一个极端的案例,因为你真的需要一个卑鄙的用户来*击败你的应用程序.我没有-1你
你应该使用`Path.Combine(String,String)`.`Path.GetTempPath()`不保证返回尾随路径分隔符,因为它基于环境变量.
如你所愿,米奇.我不能诚实地回答错误的答案,特别是当它很容易修复时.所以我会继续前进.
@Mitch见(http://en.wikipedia.org/wiki/GUID)它讨论了可预测性(可能预测下一个250,000个guid).碰撞的概率不是这里的问题,它是预测下一个GUID的可能性
任何质疑正确生成的GUID的"唯一性"的人都应该阅读FIT(时间上的失败)分析.您将很快开始考虑所有其他将首先出错的事情.比如说,即使在您的ECC服务器中也存在无法恢复的内存损坏....
更好的选择是在循环中执行它,这样如果文件存在则生成一个新的.
@BrettRyan:那是不正确的。根据文档,它将按以下顺序检查环境变量:TMP,TEMP,USERPROFILE,Windows目录。我的环境var TMP(和TEMP)没有结尾斜杠,但是对System.IO.Path.GetTempPath()的调用将附加结尾斜杠。

2> JaredPar..:

试试这个功能......

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

它将返回一个包含您选择的扩展名的完整路径.

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


我想这取决于方法的契约(是否需要`.txt`或`txt`),但由于`ChangeExtension`处理两种情况,它不会伤害
也许Path.ChangeExtension()会比Guid.NewGuid()更优雅.ToString()+扩展名

3> Maxence..:
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次尝试;


你混合了`GetTempFileName()`和`GetRandomFileName()`.`GetTempFileName()`创建一个像我的方法一样的零字节文件,但是`GetRandomFileName()`不会创建一个文件.从文档:>与GetTempFileName不同,GetRandomFileName不会创建文件.您的链接指向错误的页面.

4> Mehmet Aras..:

您也可以使用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实例.



5> Matías..:

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

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


File.Exists告诉您有关过去的信息,因此不可靠.在返回File.Exist和执行它的代码之间,可以创建文件.
...那么你可以安全地使用自己的程序,但不能与其他进程在同一目的地上编写文件...
@Migol非常低,根据定义,是一种特殊情况。嗯,到底是为异常设计的。
@CodyGray guid冲突的机会是1/2 ^ 128.它会发生2次的可能性是1/2 ^ 256等.不要打扰!

6> Colonel Pani..:

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

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

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

由于用于生成文件名的算法,GetTempFileName在创建具有相同前缀的大量文件时可能表现不佳.在这种情况下,建议您根据GUID构造唯一的文件名.


如果GetTempFileName方法用于创建超过65535个文件而不删除以前的临时文件,则会引发IOException.如果没有唯一的临时文件名可用,GetTempFileName方法将引发IOException.要解决此错误,请删除所有不需要的临时文件.

7> 小智..:

怎么样:

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

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



8> Michael Prew..:

您还可以执行以下操作

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

这也按预期工作

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


GetTempFileName保证它返回的路径是唯一的.不是它返回的路径+".csv"将是唯一的.大卫说,以这种方式改变扩展可能会失败.
GetTempFileName创建一个文件,因此您的第一个示例是资源泄漏.
如果存在temp.csv文件并且您创建temp.tmp然后将扩展名更改为csv,则会失败
推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有