วิธีที่ดีที่สุดในการรับชื่อไดเรกทอรีชั่วคราวใน Windows คืออะไร ฉันเห็นว่าฉันสามารถใช้GetTempPath
และGetTempFileName
สร้างไฟล์ชั่วคราวได้ แต่มีmkdtemp
ฟังก์ชันใดเทียบเท่ากับฟังก์ชันLinux / BSD สำหรับการสร้างไดเร็กทอรีชั่วคราวหรือไม่
วิธีที่ดีที่สุดในการรับชื่อไดเรกทอรีชั่วคราวใน 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()
เพื่อให้ไฟล์พา ธ แบบสุ่มหลอกที่ถูกต้องบนดิสก์จากนั้นลบไฟล์และสร้างไดเร็กทอรีที่มีพา ธ ไฟล์เดียวกัน
วิธีนี้หลีกเลี่ยงความจำเป็นในการตรวจสอบว่า filepath พร้อมใช้งานในชั่วขณะหรือวนซ้ำตามความคิดเห็นของ Chris ในคำตอบของ Scott Dorman
public string GetTemporaryDirectory()
{
string tempFolder = Path.GetTempFileName();
File.Delete(tempFolder);
Directory.CreateDirectory(tempFolder);
return tempFolder;
}
หากคุณต้องการชื่อสุ่มที่ปลอดภัยด้วยการเข้ารหัสอย่างแท้จริงคุณอาจต้องการปรับคำตอบของ Scott ให้ใช้ while หรือทำวนซ้ำเพื่อพยายามสร้างเส้นทางบนดิสก์ต่อไป
ฉันชอบใช้ GetTempPath () ซึ่งเป็นฟังก์ชันการสร้าง GUID เช่น CoCreateGuid () และ CreateDirectory ()
GUID ได้รับการออกแบบมาให้มีความเป็นไปได้สูงที่จะไม่ซ้ำกันและยังเป็นไปไม่ได้อย่างยิ่งที่จะมีคนสร้างไดเร็กทอรีด้วยรูปแบบเดียวกับ GUID (และหากทำเช่นนั้น CreateDirectory () จะไม่สามารถระบุการมีอยู่ได้)
@ Chris ฉันเองก็หมกมุ่นอยู่กับความเสี่ยงจากระยะไกลที่อาจมีไดเรกทอรีชั่วคราวอยู่แล้ว การอภิปรายเกี่ยวกับการสุ่มและการเข้ารหัสที่รัดกุมไม่ทำให้ฉันพอใจ
แนวทางของฉันสร้างขึ้นจากข้อเท็จจริงพื้นฐานที่ว่า 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;
}
คุณจะต้องตัดสินใจว่า "ต้นทุน / ความเสี่ยง" ของรหัส p / invoke ที่ไม่มีการจัดการนั้นคุ้มค่าหรือไม่ ส่วนใหญ่จะตอบว่าไม่ใช่ แต่อย่างน้อยคุณก็มีทางเลือกแล้ว
CreateParentFolder () จะถูกปล่อยให้เป็นแบบฝึกหัดสำหรับนักเรียน ฉันใช้ Directory.CreateDirectory () ระวังการรับพาเรนต์ของไดเร็กทอรีเนื่องจากเป็นโมฆะเมื่ออยู่ที่รูท
ฉันมักจะใช้สิ่งนี้:
/// <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;
}
หากคุณต้องการแน่ใจอย่างยิ่งว่าชื่อไดเร็กทอรีนี้จะไม่มีอยู่ใน temp path คุณต้องตรวจสอบว่าชื่อไดเร็กทอรีเฉพาะนี้มีอยู่หรือไม่และพยายามสร้างชื่อไดเร็กทอรีอื่นหากมีอยู่จริง
แต่การใช้งานตาม GUID นี้ก็เพียงพอแล้ว ฉันไม่มีประสบการณ์กับปัญหาใด ๆ ในกรณีนี้ แอปพลิเคชัน MS บางตัวใช้ไดเรกทอรีชั่วคราวตาม GUID ด้วย
ต่อไปนี้เป็นแนวทางที่ดุร้ายกว่าในการแก้ไขปัญหาการชนกันสำหรับชื่อไดเรกทอรีชั่วคราว ไม่ใช่แนวทางที่ผิดพลาด แต่จะช่วยลดโอกาสในการชนกันของเส้นทางโฟลเดอร์ได้มาก
อาจเพิ่มกระบวนการหรือข้อมูลที่เกี่ยวข้องกับแอสเซมบลีอื่น ๆ ลงในชื่อไดเร็กทอรีเพื่อให้เกิดการชนกันน้อยลงแม้ว่าการทำให้ข้อมูลดังกล่าวปรากฏในชื่อไดเร็กทอรีชั่วคราวอาจไม่เป็นที่ต้องการ นอกจากนี้คุณยังสามารถผสมลำดับที่จะรวมฟิลด์ที่เกี่ยวข้องกับเวลาเพื่อให้ชื่อโฟลเดอร์ดูสุ่มมากขึ้น โดยส่วนตัวแล้วฉันชอบที่จะปล่อยไว้แบบนั้นเพียงเพราะมันง่ายกว่าสำหรับฉันที่จะพบพวกมันทั้งหมดในระหว่างการดีบั๊ก
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);
GetTempPathเป็นวิธีที่ถูกต้องในการดำเนินการ ฉันไม่แน่ใจว่าคุณกังวลเกี่ยวกับวิธีนี้อย่างไร จากนั้นคุณสามารถใช้CreateDirectoryเพื่อสร้างได้
ดังที่ได้กล่าวมาแล้ว Path.GetTempPath () เป็นวิธีหนึ่งที่ทำได้ คุณยังสามารถเรียกEnvironment.GetEnvironmentVariable ("TEMP")หากผู้ใช้มีการตั้งค่าตัวแปรสภาพแวดล้อม TEMP
หากคุณกำลังวางแผนที่จะใช้ไดเร็กทอรี temp เป็นวิธีการคงอยู่ของข้อมูลในแอ็พพลิเคชันคุณอาจต้องดูที่การใช้IsolatedStorageเป็นที่เก็บสำหรับคอนฟิกูเรชัน / state / etc ...