Windows에서 임시 디렉터리 이름을 얻는 가장 좋은 방법은 무엇입니까? 임시 파일을 사용 GetTempPath
하고 GetTempFileName
생성 할 수 있다는 것을 알지만 mkdtemp
, 임시 디렉토리를 생성하는 데 Linux / BSD 기능 과 동일한 기능이 있습니까?
답변
아니요, mkdtemp에 해당하는 것은 없습니다. 가장 좋은 방법은 GetTempPath 및 GetRandomFileName 의 조합을 사용하는 것입니다 .
다음과 유사한 코드가 필요합니다.
public string GetTemporaryDirectory()
{
string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory(tempDirectory);
return tempDirectory;
}
답변
Path.GetTempFileName()
디스크에 유효한 의사 임의 파일 경로를 제공하기 위해 해킹 한 다음 파일을 삭제하고 동일한 파일 경로로 디렉토리를 만듭니다.
이렇게하면 Scott Dorman의 답변에 대한 Chris의 의견에 따라 파일 경로를 while 또는 loop에서 사용할 수 있는지 확인할 필요가 없습니다.
public string GetTemporaryDirectory()
{
string tempFolder = Path.GetTempFileName();
File.Delete(tempFolder);
Directory.CreateDirectory(tempFolder);
return tempFolder;
}
정말로 암호 학적으로 안전한 임의의 이름이 필요한 경우 Scott의 대답을 수정하여 while을 사용하거나 루프를 수행하여 디스크에 경로를 계속 생성하려고 할 수 있습니다.
답변
CoCreateGuid () 및 CreateDirectory ()와 같은 GUID 생성 함수 인 GetTempPath ()를 사용하고 싶습니다.
GUID는 고유성 가능성이 높도록 설계되었으며, 누군가가 GUID와 동일한 형식의 디렉터리를 수동으로 생성 할 가능성이 매우 낮습니다.
답변
@Chris. 나도 임시 디렉토리가 이미 존재할 수 있다는 원격 위험에 집착했습니다. 무작위적이고 암호 학적으로 강력한 토론도 저를 완전히 만족시키지 못합니다.
내 접근 방식은 O / S가 두 번의 호출이 모두 성공하기 위해 파일을 생성하도록 허용해서는 안된다는 근본적인 사실을 기반으로합니다. .NET 디자이너가 디렉터리에 대한 Win32 API 기능을 숨기도록 선택했다는 것은 약간 놀랍습니다. 두 번째로 디렉터리를 만들려고하면 오류가 반환되기 때문에 훨씬 쉽게 디렉터리에 대한 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 / invoke 코드의 “비용 / 위험”이 가치가 있는지 여부를 결정할 수 있습니다. 대부분은 그렇지 않다고 말할 것이지만 적어도 지금은 선택권이 있습니다.
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);