.net 创建临时文件夹

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16656/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 09:39:20  来源:igfitidea点击:

Creating temporary folders

.netio

提问by wusher

I am working on a program that needs to create a multiple temporary folders for the application. These will not be seen by the user. The app is written in VB.net. I can think of a few ways to do it such as incremental folder name or random numbered folder names, but I was wondering, how other people solve this problem?

我正在开发一个需要为应用程序创建多个临时文件夹的程序。这些将不会被用户看到。该应用程序是用 VB.net 编写的。我可以想到几种方法来做到这一点,例如增量文件夹名称或随机编号的文件夹名称,但我想知道其他人是如何解决这个问题的?

采纳答案by Rick

Update:Added File.Exists check per comment (2012-Jun-19)

更新:添加 File.Exists 检查每条评论(2012 年 6 月 19 日)

Here's what I've used in VB.NET. Essentially the same as presented, except I usually didn't want to create the folder immediately.

这是我在 VB.NET 中使用的。基本上与介绍的相同,只是我通常不想立即创建文件夹。

The advantage to use GetRandomFilenameis that it doesn't create a file, so you don't have to clean up if your using the name for something other than a file. Like using it for folder name.

使用GetRandomFilename的优点是它不会创建文件,因此如果您将名称用于文件以外的其他内容,则不必进行清理。就像将它用作文件夹名称一样。

Private Function GetTempFolder() As String
    Dim folder As String = Path.Combine(Path.GetTempPath, Path.GetRandomFileName)
    Do While Directory.Exists(folder) or File.Exists(folder)
        folder = Path.Combine(Path.GetTempPath, Path.GetRandomFileName)
    Loop

    Return folder
End Function

RandomFilename Example:

随机文件名示例:

C:\Documents and Settings\username\Local Settings\Temp\u3z5e0co.tvq

C:\Documents and Settings\用户名\Local Settings\Temp\u3z5e0co.tvq



Here's a variation using a Guid to get the temp folder name.

这是使用 Guid 获取临时文件夹名称的变体。

Private Function GetTempFolderGuid() As String
    Dim folder As String = Path.Combine(Path.GetTempPath, Guid.NewGuid.ToString)
    Do While Directory.Exists(folder) or File.Exists(folder)
        folder = Path.Combine(Path.GetTempPath, Guid.NewGuid.ToString)
    Loop

    Return folder
End Function

guidExample:

指导示例:

C:\Documents and Settings\username\Local Settings\Temp\2dbc6db7-2d45-4b75-b27f-0bd492c60496

C:\Documents and Settings\用户名\Local Settings\Temp\2dbc6db7-2d45-4b75-b27f-0bd492c60496

回答by juan

You have to use System.IO.Path.GetTempFileName()

你必须使用 System.IO.Path.GetTempFileName()

Creates a uniquely named, zero-byte temporary file on disk and returns the full path of that file.

在磁盘上创建一个唯一命名的零字节临时文件并返回该文件的完整路径。

You can use System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName())to get only the temp folder information, and create your folders in there

您可以使用System.IO.Path.GetDirectoryName(System.IO.Path.GetTempFileName())仅获取临时文件夹信息,并在其中创建文件夹

They are created in the windows temp folder and that's consider a best practice

它们是在 windows temp 文件夹中创建的,这被认为是最佳实践

回答by urini

Just to clarify:

只是为了澄清:

System.IO.Path.GetTempPath()

returns just the folder path to the temp folder.

仅返回临时文件夹的文件夹路径。

System.IO.Path.GetTempFileName()

returns the fully qualified file name (including the path) so this:

返回完全限定的文件名(包括路径),因此:

System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetTempFileName())

is redundant.

是多余的。

回答by Jonathan Wright

There's a possible race condition when:

在以下情况下可能存在竞争条件:

  • creating a temp file with GetTempFileName(), deleting it, and making a folder with the same name, or
  • using GetRandomFileName()or Guid.NewGuid.ToStringto name a folder and creating the folder later
  • 创建一个临时文件GetTempFileName(),删除它,然后创建一个同名的文件夹,或者
  • 使用GetRandomFileName()Guid.NewGuid.ToString命名文件夹并稍后创建文件夹

With GetTempFileName()after the delete occurs, another application could successfully create a temp file with the same name. The CreateDirectory()would then fail.

随着GetTempFileName()删除发生之后,另一个应用程序可以成功地创建具有相同名称的临时文件。然后CreateDirectory()就会失败。

Similarly, between calling GetRandomFileName()and creating the directory another process could create a file or directory with the same name, again resulting in CreateDirectory()failing.

同样,在调用GetRandomFileName()和创建目录之间,另一个进程可能会创建同名的文件或目录,再次导致CreateDirectory()失败。

For most applications it's OK for a temp directory to fail due to a race condition. It's extremely rare after all. For them, these races can often be ignored.

对于大多数应用程序,临时目录由于竞争条件而失败是可以的。毕竟是极其罕见的。对他们来说,这些种族往往可以被忽略。

In the Unix shell scripting world, creating temp files and directories in a safe race-free way is a big deal. Many machines have multiple (hostile) users -- think shared web host -- and many scripts and applications need to safely create temp files and directories in the shared /tmp directory. See Safely Creating Temporary Files in Shell Scriptsfor a discussion on how to safely create temp directories from shell scripts.

在 Unix shell 脚本世界中,以安全的无竞争方式创建临时文件和目录是一件大事。许多机器有多个(敌对)用户——比如共享网络主机——并且许多脚本和应用程序需要在共享的 /tmp 目录中安全地创建临时文件和目录。有关如何从 shell 脚本安全地创建临时目录的讨论,请参阅在 Shell 脚本中安全创建临时文件

回答by Daniel Trebbien

As @JonathanWright pointed out, race conditions exist for the solutions:

正如@JonathanWright指出的那样,解决方案存在竞争条件:

  • Create a temporary file with GetTempFileName(), delete it, and create a folder with the same name
  • Use GetRandomFileName()or Guid.NewGuid.ToStringto create a random folder name, check whether it exists, and create it if not.
  • 创建一个临时文件GetTempFileName(),删除它,并创建一个同名文件夹
  • 使用GetRandomFileName()Guid.NewGuid.ToString来创建一个随机文件夹名称,检查它是否存在,如果不存在则创建它。

It is possible, however, to create a unique temporary directory atomically by utilizing the Transactional NTFS(TxF) API.

但是,可以通过使用Transactional NTFS(TxF) API以原子方式创建唯一的临时目录。

TxF has a CreateDirectoryTransacted()function that can be invoked via Platform Invoke. To do this, I adapted Mohammad Elsheimy's codefor calling CreateFileTransacted():

TxF 有一个CreateDirectoryTransacted()可以通过 Platform Invoke 调用的函数。为此,我修改了Mohammad Elsheimy 的调用代码CreateFileTransacted()

// using System.ComponentModel;
// using System.Runtime.InteropServices;
// using System.Transactions;

[ComImport]
[Guid("79427a2b-f895-40e0-be79-b57dc82ed231")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IKernelTransaction
{
    void GetHandle(out IntPtr pHandle);
}

// 2.2 Win32 Error Codes <http://msdn.microsoft.com/en-us/library/cc231199.aspx>
public const int ERROR_PATH_NOT_FOUND = 0x3;
public const int ERROR_ALREADY_EXISTS = 0xb7;
public const int ERROR_EFS_NOT_ALLOWED_IN_TRANSACTION = 0x1aaf;

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool CreateDirectoryTransacted(string lpTemplateDirectory, string lpNewDirectory, IntPtr lpSecurityAttributes, IntPtr hTransaction);

/// <summary>
/// Creates a uniquely-named directory in the directory named by <paramref name="tempPath"/> and returns the path to it.
/// </summary>
/// <param name="tempPath">Path of a directory in which the temporary directory will be created.</param>
/// <returns>The path of the newly-created temporary directory within <paramref name="tempPath"/>.</returns>
public static string GetTempDirectoryName(string tempPath)
{
    string retPath;

    using (TransactionScope transactionScope = new TransactionScope())
    {
        IKernelTransaction kernelTransaction = (IKernelTransaction)TransactionInterop.GetDtcTransaction(Transaction.Current);
        IntPtr hTransaction;
        kernelTransaction.GetHandle(out hTransaction);

        while (!CreateDirectoryTransacted(null, retPath = Path.Combine(tempPath, Path.GetRandomFileName()), IntPtr.Zero, hTransaction))
        {
            int lastWin32Error = Marshal.GetLastWin32Error();
            switch (lastWin32Error)
            {
                case ERROR_ALREADY_EXISTS:
                    break;
                default:
                    throw new Win32Exception(lastWin32Error);
            }
        }

        transactionScope.Complete();
    }
    return retPath;
}

/// <summary>
/// Equivalent to <c>GetTempDirectoryName(Path.GetTempPath())</c>.
/// </summary>
/// <seealso cref="GetTempDirectoryName(string)"/>
public static string GetTempDirectoryName()
{
    return GetTempDirectoryName(Path.GetTempPath());
}

回答by Adam Wright

Something like...

就像是...

using System.IO;

string path = Path.GetTempPath() + Path.GetRandomFileName();
while (Directory.Exists(path))
 path = Path.GetTempPath() + Path.GetRandomFileName();

Directory.CreateDirectory(path);

回答by Andrew Rimmer

You could generate a GUID for your temporary folder names.

您可以为临时文件夹名称生成一个 GUID。

回答by pix0r

You can use GetTempFileNameto create a temporary file, then delete and re-create this file as a directory instead.

您可以使用GetTempFileName创建一个临时文件,然后删除并重新创建该文件作为目录。

Note: link didn't work, copy/paste from: http://msdn.microsoft.com/en-us/library/aa364991(VS.85).aspx

注意:链接无效,复制/粘贴来自:http: //msdn.microsoft.com/en-us/library/aa364991(VS.85).aspx

回答by jwalkerjr

As long as the name of the folder doesn't need to be meaningful, how about using a GUID for them?

只要文件夹的名称不需要有意义,那么为它们使用 GUID 怎么样?

回答by Brian G Swanson

Combined answers from @adam-wright and pix0r will work the best IMHO:

来自@adam-wright 和 pix0r 的综合答案将是最好的恕我直言:


using System.IO;

string path = Path.GetTempPath() + Path.GetRandomFileName();

while (Directory.Exists(path)) 
  path = Path.GetTempPath() + Path.GetRandomFileName();

File.Delete(path);
Directory.CreateDirectory(path);