在Windows中创建临时目录?

时间:2008-11-10 16:50:35

标签: c# .net windows temporary-directory

在Windows中获取临时目录名称的最佳方法是什么?我看到我可以使用GetTempPathGetTempFileName来创建临时文件,但是有没有相当于Linux / BSD mkdtemp函数来创建临时目录?

9 个答案:

答案 0 :(得分:207)

不,没有相当于mkdtemp的东西。最佳选择是使用GetTempPathGetRandomFileName的组合。

您需要与此类似的代码:

public string GetTemporaryDirectory()
{
   string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
   Directory.CreateDirectory(tempDirectory);
   return tempDirectory;
}

答案 1 :(得分:20)

我骇客Path.GetTempFileName()在磁盘上给我一个有效的伪随机文件路径,然后删除该文件,并创建一个具有相同文件路径的目录。

根据Chris对Scott Dorman回答的评论,这可以避免检查文件路径是否在一段时间或循环中可用。

public string GetTemporaryDirectory()
{
  string tempFolder = Path.GetTempFileName();
  File.Delete(tempFolder);
  Directory.CreateDirectory(tempFolder);

  return tempFolder;
}

如果您确实需要加密安全的随机名称,您可能需要调整Scott的答案以使用while或do循环来继续尝试在磁盘上创建路径。

答案 2 :(得分:7)

我喜欢使用GetTempPath(),像CoCreateGuid()这样的GUID创建函数,以及CreateDirectory()。

GUID被设计为具有很高的唯一性概率,并且非常不可能有人手动创建与GUID具有相同形式的目录(如果他们这样做,那么CreateDirectory()将失败以指示其存在。)

答案 3 :(得分:5)

@克里斯。我也很痴迷于临时目录可能已经存在的远程风险。关于随机和密码强的讨论也不能完全满足我。

我的方法建立在O / S必须不允许2次调用创建文件才能成功的基本事实的基础上。 .NET设计人员选择隐藏目录的Win32 API功能有点令人惊讶,这使得这更容易,因为当您尝试第二次创建目录时它会返回错误。这是我使用的:

    [DllImport(@"kernel32.dll", EntryPoint = "CreateDirectory", SetLastError = true, CharSet = CharSet.Unicode)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool CreateDirectoryApi
        ([MarshalAs(UnmanagedType.LPTStr)] string lpPathName, IntPtr lpSecurityAttributes);

    /// <summary>
    /// Creates the directory if it does not exist.
    /// </summary>
    /// <param name="directoryPath">The directory path.</param>
    /// <returns>Returns false if directory already exists. Exceptions for any other errors</returns>
    /// <exception cref="System.ComponentModel.Win32Exception"></exception>
    internal static bool CreateDirectoryIfItDoesNotExist([NotNull] string directoryPath)
    {
        if (directoryPath == null) throw new ArgumentNullException("directoryPath");

        // First ensure parent exists, since the WIN Api does not
        CreateParentFolder(directoryPath);

        if (!CreateDirectoryApi(directoryPath, lpSecurityAttributes: IntPtr.Zero))
        {
            Win32Exception lastException = new Win32Exception();

            const int ERROR_ALREADY_EXISTS = 183;
            if (lastException.NativeErrorCode == ERROR_ALREADY_EXISTS) return false;

            throw new System.IO.IOException(
                "An exception occurred while creating directory'" + directoryPath + "'".NewLine() + lastException);
        }

        return true;
    }

您可以决定&#34;成本/风险&#34;非托管p / invoke代码是值得的。大多数人会说它不是,但至少你现在可以选择。

CreateParentFolder()作为练习留给学生。我使用Directory.CreateDirectory()。小心获取目录的父目录,因为它在根目录时为空。

答案 4 :(得分:2)

GetTempPath是正确的做法;我不确定你对这种方法的关注是什么。然后,您可以使用CreateDirectory来制作它。

答案 5 :(得分:1)

这是解决临时目录名称的冲突问题的一种更强大的方法。它不是一种绝对可靠的方法,但它大大减少了文件夹路径冲突的可能性。

可能会将其他进程或程序集相关信息添加到目录名称,以使冲突更不可能发生,尽管可能不希望在临时目录名称上显示此类信息。还可以混合与时间相关的字段组合的顺序,以使文件夹名称看起来更随机。我个人更喜欢这样做,因为在调试过程中我更容易找到它们。

string randomlyGeneratedFolderNamePart = Path.GetFileNameWithoutExtension(Path.GetRandomFileName());

string timeRelatedFolderNamePart = DateTime.Now.Year.ToString()
                                 + DateTime.Now.Month.ToString()
                                 + DateTime.Now.Day.ToString()
                                 + DateTime.Now.Hour.ToString()
                                 + DateTime.Now.Minute.ToString()
                                 + DateTime.Now.Second.ToString()
                                 + DateTime.Now.Millisecond.ToString();

string processRelatedFolderNamePart = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();

string temporaryDirectoryName = Path.Combine( Path.GetTempPath()
                                            , timeRelatedFolderNamePart 
                                            + processRelatedFolderNamePart 
                                            + randomlyGeneratedFolderNamePart);

答案 6 :(得分:1)

我通常使用它:

    /// <summary>
    /// Creates the unique temporary directory.
    /// </summary>
    /// <returns>
    /// Directory path.
    /// </returns>
    public string CreateUniqueTempDirectory()
    {
        var uniqueTempDir = Path.GetFullPath(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
        Directory.CreateDirectory(uniqueTempDir);
        return uniqueTempDir;
    }

如果您想要绝对确定此目录名称在临时路径中不存在,那么您需要检查此唯一目录名称是否存在,并尝试创建另一个目录名称(如果它确实存在)。

但是这个基于GUID的实现就足够了。在这种情况下我没有遇到任何问题的经验。一些MS应用程序也使用基于GUID的临时目录。

答案 7 :(得分:0)

如上所述,Path.GetTempPath()是一种方法。如果用户设置了TEMP环境变量,您也可以调用Environment.GetEnvironmentVariable("TEMP")

如果您打算使用临时目录作为在应用程序中保存数据的方法,您可能应该考虑使用IsolatedStorage作为配置/状态/等的存储库...

答案 8 :(得分:0)

我使用了一些答案,并以此方式实现了GetTmpDirectory方法。

public string GetTmpDirectory()
{
    string tmpDirectory;

    do
    {
        tmpDirectory = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(Path.GetRandomFileName()));
    } while (Directory.Exists(tmpDirectory));

    Directory.CreateDirectory(tmpDirectory);
    return tmpDirectory;
}