在Windows中获取临时目录名称的最佳方法是什么?我看到可以使用GetTempPath
并GetTempFileName
创建一个临时文件,但是是否有等效于Linux / BSD的mkdtemp
功能来创建临时目录?
在Windows中获取临时目录名称的最佳方法是什么?我看到可以使用GetTempPath
并GetTempFileName
创建一个临时文件,但是是否有等效于Linux / BSD的mkdtemp
功能来创建临时目录?
Answers:
不,没有等效于mkdtemp。最好的选择是结合使用GetTempPath和GetRandomFileName。
您将需要类似于以下代码:
public string GetTemporaryDirectory()
{
string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
return tempDirectory;
}
我砍 Path.GetTempFileName()
给我磁盘上一个有效的伪随机文件路径,然后删除该文件,并创建一个具有相同文件路径的目录。
根据Chris对Scott Dorman回答的评论,这避免了检查文件路径是否在一段时间或循环中可用的需要。
public string GetTemporaryDirectory()
{
string tempFolder = Path.GetTempFileName();
File.Delete(tempFolder);
Directory.CreateDirectory(tempFolder);
return tempFolder;
}
如果确实需要加密安全的随机名称,则可能需要调整Scott的答案以使用while或do循环以继续尝试在磁盘上创建路径。
@克里斯。我也很迷恋可能已经存在一个临时目录的远程风险。关于随机性和加密性强的讨论也没有完全令我满意。
我的方法基于以下基本事实:操作系统不允许两个调用创建一个文件才能成功。.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;
}
您可以确定非托管p /调用代码的“成本/风险”是否值得。大多数人会说不是,但是至少您现在可以选择。
CreateParentFolder()作为练习留给学生。我使用Directory.CreateDirectory()。小心获取目录的父目录,因为在根目录时该目录为null。
我通常使用这个:
/// <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的临时目录。
GetTempPath是正确的方法。我不确定您对此方法有何顾虑。然后,您可以使用CreateDirectory进行创建。
这是解决临时目录名称冲突问题的一种更蛮力的方法。这不是一个可靠的方法,但是它可以大大减少文件夹路径冲突的机会。
一个人可能会在目录名中添加其他与进程或程序集相关的信息,以使冲突的可能性更小,尽管使这种信息在临时目录名上可见是不希望的。也可以混合使用与时间相关的字段的顺序,以使文件夹名称看起来更加随机。我个人更喜欢以这种方式保留它,因为在调试过程中我更容易找到它们。
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);
如上所述,Path.GetTempPath()是一种实现方法。您也可以调用Environment.GetEnvironmentVariable(“ TEMP”)如果用户设置了TEMP环境变量,则。
如果您打算使用temp目录作为在应用程序中持久存储数据的一种方式,则可能应该考虑将IsolatedStorage用作配置/状态/等的存储库。