2008-11-10 16 views
84

विंडोज में अस्थायी निर्देशिका नाम प्राप्त करने का सबसे अच्छा तरीका क्या है? मैं देखता हूं कि अस्थायी फ़ाइल बनाने के लिए मैं GetTempPath और GetTempFileName का उपयोग कर सकता हूं, लेकिन क्या अस्थायी निर्देशिका बनाने के लिए लिनक्स/बीएसडी mkdtemp फ़ंक्शन के बराबर है?विंडोज में एक अस्थायी निर्देशिका बनाना?

+0

यह प्रश्न खोजने के लिए थोड़ा मुश्किल लगता है। विशेष रूप से, यदि आप स्टैक ओवरफ़्लो खोज बॉक्स में "temp निर्देशिका .net" जैसी चीजें टाइप करते हैं, तो यह प्रदर्शित नहीं होता है। यह दुर्भाग्यपूर्ण प्रतीत होता है, क्योंकि उत्तर अब तक सभी .NET उत्तरों हैं। क्या आपको लगता है कि आप ".net" टैग जोड़ सकते हैं? (और शायद "निर्देशिका" या "अस्थायी-निर्देशिका" टैग?) या शायद शीर्षक में ".NET" शब्द जोड़ें? हो सकता है कि सवाल शरीर में वैकल्पिक "अस्थायी" के साथ "अस्थायी" कहें - तो यदि आप छोटे फॉर्म की खोज करते हैं तो आपको अभी भी एक अच्छा टेक्स्ट खोज मैच मिल जाएगा। मुझे लगता है कि इन चीजों को खुद करने के लिए पर्याप्त प्रतिनिधि नहीं हैं। धन्यवाद। – Chris

+0

ठीक है, मैं एक गैर- .NET उत्तर की तलाश में था, इसलिए मैं इसे छोड़ना पसंद करूंगा, लेकिन मैंने आपके द्वारा सुझाए गए अन्य संपादन किए हैं। धन्यवाद। –

+0

@ जोश केली: मैंने अभी Win32 एपीआई को दोबारा जांच लिया है और अस्थायी पथ प्राप्त करने के समान दृष्टिकोण का पालन करने के लिए एकमात्र विकल्प हैं, एक रैमडोम फ़ाइल नाम उत्पन्न करना, और फिर निर्देशिका बनाना। –

उत्तर

165

नहीं, mkdtemp के बराबर नहीं है। सबसे अच्छा विकल्प GetTempPath और GetRandomFileName के संयोजन का उपयोग करना है।

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

@Will: मेरे टाइपो को संपादित करने और सुधारने के लिए धन्यवाद! एक बहुत अधिक प्रतिलिपि/पेस्ट त्रुटियों। :( –

+3

यह थोड़ा खतरनाक प्रतीत होता है। विशेष रूप से, एक मौका है (छोटा, लेकिन शून्य, सही?) कि पथ। कॉम्बाइन (पथ। गेटटेम्पाथ(), पथ। गेटरैंडमफाइलनाम()) निर्देशिका का नाम वापस कर देगा जो पहले से मौजूद है। निर्देशिका के बाद से। निर्देशिका डायरेक्ट्री (tempDirectory) एक अपवाद नहीं फेंक देगा यदि tempDirectory पहले से मौजूद है, तो यह मामला आपके एप्लिकेशन द्वारा नहीं पता लगाया जाएगा। और फिर आपके पास एक दूसरे के काम पर दो अनुप्रयोग चल सकते हैं। क्या वहां है .NET? – Chris

+19

@Chris में कोई सुरक्षित विकल्प: GetRandomFileName विधि एक क्रिप्टोग्राफ़िक रूप से मजबूत, यादृच्छिक स्ट्रिंग देता है जिसे किसी फ़ोल्डर नाम या फ़ाइल नाम के रूप में उपयोग किया जा सकता है। मुझे लगता है कि यह सैद्धांतिक रूप से संभव है कि परिणामस्वरूप पथ पहले से मौजूद हो सकता है, लेकिन वहां ऐसा करने के अन्य कोई अन्य तरीके नहीं हैं। आप यह देखने के लिए जांच सकते हैं कि पथ मौजूद है या नहीं, और यदि यह पथ पथ। GetRandomFileName() को दोबारा कॉल करता है, और दोहराता है। –

1

GetTempPath ऐसा करने का सही तरीका है; मुझे यकीन नहीं है कि इस विधि के बारे में आपकी चिंता क्या है। इसके बाद आप इसे बनाने के लिए CreateDirectory का उपयोग कर सकते हैं।

+0

एक समस्या यह है कि GetTempFileName शून्य-बाइट फ़ाइल बनाएगा। आपको इसके बजाय GetTempPath, GetRandomFileName और CreateDirectory का उपयोग करने की आवश्यकता है। –

+0

जो ठीक है, संभव है, और करने योग्य है। मैं कोड प्रदान करने जा रहा था लेकिन डोर्मन इसे मेरे सामने मिला, और यह सही ढंग से काम करता है। – Will

0

ऊपर उल्लेख किया है, Path.GetTempPath() एक ही रास्ता यह करने के लिए है:

आप इस के समान कोड की आवश्यकता होगी। यदि उपयोगकर्ता में एक TEMP पर्यावरण चर सेट अप है तो आप Environment.GetEnvironmentVariable("TEMP") पर भी कॉल कर सकते हैं।

आप आवेदन में डेटा बने के साधन के रूप अस्थायी निर्देशिका का उपयोग करने पर योजना बना रहे हैं, तो आप शायद विन्यास/राज्य/आदि के लिए एक भंडार के रूप में IsolatedStorage का उपयोग कर पर गौर करना चाहिए ...

7

मैं का उपयोग करना चाहते GetTempPath(), एक GUID- निर्माण फ़ंक्शन जैसे CoCreateGuid(), और CreateDirectory()।

एक GUID विशिष्टता की उच्च संभावना रखने के लिए डिज़ाइन किया गया है, और यह भी बेहद असंभव है कि कोई मैन्युअल रूप से GUID के रूप में एक ही रूप से निर्देशिका बनायेगा (और यदि वे करते हैं तो CreateDirectory() इसके अस्तित्व को इंगित करने में विफल रहेगा।)

16

मुझे डिस्क पर एक वैध, छद्म-यादृच्छिक फ़ाइलपैथ देने के लिए Path.GetTempFileName() हैक करें, फिर फ़ाइल को हटाएं, और उसी फ़ाइल पथ के साथ निर्देशिका बनाएं।

यह स्कॉट डोर्मन के उत्तर पर प्रति क्रिस की टिप्पणी के अनुसार फ़ाइलपैथ थोड़ी देर या लूप में उपलब्ध है या नहीं, यह जांचने की आवश्यकता से बचाता है।

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

    return tempFolder; 
} 

आप वास्तव में एक क्रिप्टोग्राफी द्वारा सुरक्षित यादृच्छिक नाम की जरूरत है, आप थोड़ी देर का उपयोग करें या डिस्क पर एक रास्ता बनाने का प्रयास कर रखने के लिए पाश करने के लिए स्कॉट जवाब अनुकूल करने के लिए कर सकते हैं।

+0

यह एक साफ छोटी चाल है! – JMS10

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); 
2

@ क्रिस। मैं भी रिमोट जोखिम से भ्रमित था कि एक अस्थायी निर्देशिका पहले से मौजूद हो सकती है। यादृच्छिक और क्रिप्टोग्राफिक रूप से मजबूत के बारे में चर्चा पूरी तरह से मुझे संतुष्ट नहीं करती है।

मेरा दृष्टिकोण मौलिक तथ्य पर बनाता है कि ओ/एस को सफल होने के लिए 2 कॉल करने की अनुमति नहीं देनी चाहिए। यह थोड़ा आश्चर्यजनक है कि।नेट डिजाइनरों ने निर्देशिकाओं के लिए 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; 
    } 

आपको तय करना है कि क्या अप्रबंधित पी के 'लागत/जोखिम "/ आह्वान कोड इसके लायक है मिलती है: यहाँ मैं क्या उपयोग है। ज्यादातर लोग कहते हैं कि यह नहीं है, लेकिन कम से कम अब आपके पास एक विकल्प है।

CreateParentFolder() को छात्र के लिए एक अभ्यास के रूप में छोड़ दिया गया है। मैं Directory.CreateDirectory() का उपयोग करता हूं। एक निर्देशिका के माता-पिता को सावधान रहें, क्योंकि रूट पर यह शून्य है।

0

मैं आमतौर पर इस का उपयोग करें:

/// <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- आधारित कार्यान्वयन पर्याप्त है। मुझे इस मामले में किसी भी समस्या के साथ कोई अनुभव नहीं है। कुछ एमएस अनुप्रयोग GUID आधारित temp निर्देशिकाओं का भी उपयोग करते हैं।

संबंधित मुद्दे