विंडोज में एक अस्थायी निर्देशिका बनाना?


126

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


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

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

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

जवाबों:


230

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

आपको इसके समान कोड की आवश्यकता होगी:

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

3
यह थोड़ा खतरनाक लगता है। विशेष रूप से, एक मौका है (छोटा, लेकिन गैर-शून्य, दाएं?) कि Path.Combine (Path.GetTempPath) (), Path.GetRandomFileName ()) एक निर्देशिका का नाम लौटाएगा जो पहले से मौजूद है। जब से tempDirectory पहले से मौजूद है, तब Directory.CreateDirectory (tempDirectory) अपवाद को नहीं फेंकेगी, इस मामले का आपके एप्लिकेशन द्वारा पता नहीं लगाया जाएगा। और फिर आपके पास एक दूसरे के काम के लिए दो कदम हो सकते हैं। क्या .NET में कोई सुरक्षित विकल्प है?
क्रिस

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

5
@ क्रिस: यदि आप उस सीमा तक सुरक्षा के बारे में चिंतित हैं, तो एक बहुत ही पतली संभावना है कि एक और प्रक्रिया पथ.कॉम्बिन और डायरेक्टरी के बीच निर्देशिका बना सकती है।
स्कॉट डॉरमैन

8
GetRandomFileName 11 यादृच्छिक लोअरकेस अक्षर और संख्या उत्पन्न करता है जिसका अर्थ है कि डोमेन आकार (26 + 10) ^ 11 = ~ 57 बिट्स। आप हमेशा इसे कॉल करने के लिए दो कॉल कर सकते हैं
मार्टी नील

27
आपके द्वारा यह जाँचने के बाद कि निर्देशिका मौजूद नहीं है, ईश्वर ब्रह्मांड को रोक सकता है, चुपके से उसी निर्देशिका को बना सकता है, जिसमें आप लिखी जाने वाली सभी फाइलों के साथ हैं, जिससे आपका ऐप उड़ जाएगा, बस आपका दिन बर्बाद हो जाएगा।
त्रिनको

25

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

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

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

  return tempFolder;
}

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


7

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

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


5

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

मेरा दृष्टिकोण मौलिक तथ्य पर निर्भर करता है कि ओ / एस को सफल होने के लिए फ़ाइल बनाने के लिए 2 कॉल की अनुमति नहीं देनी चाहिए। यह थोड़ा आश्चर्य की बात है कि .NET डिजाइनरों ने निर्देशिकाओं के लिए Win32 एपीआई कार्यक्षमता को छिपाने के लिए चुना, जो इसे बहुत आसान बनाता है, क्योंकि जब आप दूसरी बार निर्देशिका बनाने का प्रयास करते हैं तो यह एक त्रुटि देता है। यहाँ मेरा उपयोग है:

    [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 () का उपयोग करता हूं। एक मूल के माता-पिता को प्राप्त करने से सावधान रहें, क्योंकि यह जड़ में होने पर अशक्त है।


5

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

    /// <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 आधारित अस्थायी निर्देशिकाओं का भी उपयोग करते हैं।


1

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


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

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

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

0

जैसा कि ऊपर बताया गया है, Path.GetTempPath () इसे करने का एक तरीका है। यदि उपयोगकर्ता के पास TEMP परिवेश चर है, तो आप Environment.GetEnvironmentVariable ("TEMP") भी कॉल कर सकते हैं ।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.