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


364

क्या जावा एप्लिकेशन के अंदर एक अस्थायी निर्देशिका बनाने का एक मानक और विश्वसनीय तरीका है? नहीं है जावा के मुद्दे डेटाबेस में एक प्रविष्टि है, जो टिप्पणी में कोड का एक सा है, लेकिन मुझे आश्चर्य है कि अगर वहाँ एक मानक समाधान सामान्य पुस्तकालयों (अपाचे कॉमन्स आदि) में से एक में पाया जा सकता है?

जवाबों:


390

यदि आप JDK 7 का उपयोग कर रहे हैं तो अस्थायी निर्देशिका बनाने के लिए नई Files.createTempDirectory वर्ग का उपयोग करें।

Path tempDirWithPrefix = Files.createTempDirectory(prefix);

जेडीके 7 से पहले यह करना चाहिए:

public static File createTempDirectory()
    throws IOException
{
    final File temp;

    temp = File.createTempFile("temp", Long.toString(System.nanoTime()));

    if(!(temp.delete()))
    {
        throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
    }

    if(!(temp.mkdir()))
    {
        throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
    }

    return (temp);
}

यदि आप चाहें तो आप बेहतर अपवाद (उपवर्ग IOException) बना सकते हैं।


12
यह खतरनाक है। जावा तुरंत फ़ाइलों को नहीं हटाने के लिए जाना जाता है, इसलिए mkdir कभी
डेमिएर

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

6
@Demiurg जावा तुरंत फ़ाइलों को हटाने के लिए नहीं जाना जाता है। यह सच है, भले ही आप इसे न खोलें। तो, एक अधिक सुरक्षित तरीका है temp.delete(); temp = new File(temp.getPath + ".d"); temp.mkdir(); ..., temp.delete();
ग्यारहवीं जेली

102
इस कोड के बीच एक दौड़ की स्थिति है delete()और mkdir(): एक दुर्भावनापूर्ण प्रक्रिया इस बीच लक्ष्य निर्देशिका बना सकती है (हाल ही में बनाई गई फ़ाइल का नाम लेकर)। Files.createTempDir()एक विकल्प के लिए देखें ।
जोकिम सॉयर

11
मुझे पसंद है ! बाहर खड़े होने के लिए, यह याद रखना बहुत आसान है। मैंने छात्रों द्वारा लिखे गए बहुत सारे कोड पढ़े हैं ... यदि (i) परेशान होने के लिए आम है तो :-)
टोफूबीर

182

Google अमरूद पुस्तकालय में उपयोगी उपयोगिताओं का एक टन है। यहां एक ध्यान दें कि फाइल क्लास है । इसमें उपयोगी तरीकों का एक समूह है:

File myTempDir = Files.createTempDir();

यह वही करता है जो आपने एक लाइन में मांगा था। यदि आप यहां प्रलेखन पढ़ते हैं, तो आप देखेंगे कि प्रस्तावित अनुकूलन File.createTempFile("install", "dir")आमतौर पर सुरक्षा कमजोरियों का परिचय देता है।


मुझे आश्चर्य है कि आप किस भेद्यता का उल्लेख करते हैं। यह स्थिति किसी रेस कंडीशन को बनाने के लिए नहीं दिखाई देती है क्योंकि File.mkdir () को विफल कर दिया जाता है यदि ऐसी डायरेक्टरी पहले से मौजूद है (हमलावर द्वारा बनाई गई)। मुझे नहीं लगता कि यह कॉल किसी दुर्भावनापूर्ण सिम्बलिंक के माध्यम से अनुसरण करेगा। क्या आप स्पष्ट कर सकते हैं कि आपका क्या मतलब है?
11:27

3
@abb: मुझे उस अमर्यादित स्थिति का विवरण नहीं है जो अमरूद के दस्तावेज में वर्णित है। मुझे संदेह है कि प्रलेखन सही है कि यह विशेष रूप से समस्या को बुलावा देता है।
Spina

1
@abb आप सही कह रहे हैं। जब तक mkdir () की वापसी की जाँच की जाती है, तब तक यह सुरक्षित होगा। कोड Spina इस mkdir () विधि का उपयोग करने के लिए इंगित करता है। grepcode.com/file/repo1.maven.org/maven2/com.google.guava/guava/… । यह / tmp निर्देशिका का उपयोग करते समय यूनिक्स सिस्टम पर केवल एक संभावित मुद्दा है क्योंकि इसमें चिपचिपा बिट सक्षम है।
सेरेल बोथा

@ सेरेलबोथा यहां रिक्त स्थान को भरने के लिए धन्यवाद। मैं काफी समय से इस बारे में मूर्खतापूर्ण सोच रहा था।
Spina

168

यदि आपको परीक्षण के लिए एक अस्थायी निर्देशिका की आवश्यकता है और आप अपनी समस्या हल कर रहे हैं, तो @Ruleसाथ में jUnit का उपयोग कर रहे हैं TemporaryFolder:

@Rule
public TemporaryFolder folder = new TemporaryFolder();

से प्रलेखन :

TemporaryFolder नियम उन फ़ाइलों और फ़ोल्डरों के निर्माण की अनुमति देता है जिन्हें परीक्षण विधि समाप्त होने पर हटाए जाने की गारंटी दी जाती है (चाहे वह पास हो या न हो)


अपडेट करें:

यदि आप JUnit Jupiter (5.1.1 या अधिक संस्करण) का उपयोग कर रहे हैं, तो आपके पास JUnit Pioneer का उपयोग करने का विकल्प है जो JUnit 5 एक्सटेंशन पैक है।

परियोजना प्रलेखन से नकल :

उदाहरण के लिए, निम्न परीक्षण एकल परीक्षण विधि के लिए विस्तार को पंजीकृत करता है, अस्थायी निर्देशिका में एक फ़ाइल बनाता है और लिखता है और इसकी सामग्री की जांच करता है।

@Test
@ExtendWith(TempDirectory.class)
void test(@TempDir Path tempDir) {
    Path file = tempDir.resolve("test.txt");
    writeFile(file);
    assertExpectedFileContent(file);
}

JavaDoc और TemDDirectory के JavaDoc में अधिक जानकारी

Gradle:

dependencies {
    testImplementation 'org.junit-pioneer:junit-pioneer:0.1.2'
}

Maven:

<dependency>
   <groupId>org.junit-pioneer</groupId>
   <artifactId>junit-pioneer</artifactId>
   <version>0.1.2</version>
   <scope>test</scope>
</dependency>

अपडेट 2:

@TempDir एनोटेशन एक प्रायोगिक सुविधा के रूप में JUnit बृहस्पति 5.4.0 रिलीज करने के लिए जोड़ा गया है। उदाहरण JUnit 5 उपयोगकर्ता गाइड से कॉपी किया गया :

@Test
void writeItemsToFile(@TempDir Path tempDir) throws IOException {
    Path file = tempDir.resolve("test.txt");

    new ListWriter(file).write("a", "b", "c");

    assertEquals(singletonList("a,b,c"), Files.readAllLines(file));
}

8
JUnit 4.7 के बाद से उपलब्ध
Eduard Wirch

विंडोज 7 पर JUnit 4.8.2 में काम नहीं करता है! (अनुमतियाँ जारी)
अपवाद

2
@ क्रेगिंगर: इस पर भरोसा करना नासमझी क्यों है?
एडम पार्किन

2
@AdamParkin ईमानदारी से, मुझे अब याद नहीं है। स्पष्टीकरण विफल!
क्रेग रिंगर

1
इस दृष्टिकोण का मुख्य लाभ यह है कि निर्देशिका को JUnit द्वारा प्रबंधित किया जाता है (परीक्षण से पहले बनाया गया और परीक्षण के बाद पुन: हटा दिया गया)। और यह काम करता है। यदि आपको "अस्थायी डीआरआर अभी तक नहीं बनाया गया है", तो यह हो सकता है क्योंकि आप सार्वजनिक रूप से @Rule या फ़ील्ड भूल गए हैं।
बोगदान कालम

42

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

लेकिन JDK 7 के रूप में, अच्छी खबर है! स्वयं जावा मानक पुस्तकालय अब इस समस्या का एक उचित रूप से काम कर रहा है। आप java.nio.file.Files # createTempDirectory () चाहते हैं । से प्रलेखन :

public static Path createTempDirectory(Path dir,
                       String prefix,
                       FileAttribute<?>... attrs)
                                throws IOException

अपना नाम उत्पन्न करने के लिए दिए गए उपसर्ग का उपयोग करके, निर्दिष्ट निर्देशिका में एक नई निर्देशिका बनाता है। परिणामी पथ दिए गए निर्देशिका के समान फ़ाइल सिस्टम के साथ जुड़ा हुआ है।

निर्देशिका के नाम का निर्माण कैसे किया जाता है इसका विवरण कार्यान्वयन पर निर्भर है और इसलिए निर्दिष्ट नहीं है। जहाँ उम्मीदवार नामों के निर्माण के लिए उपसर्ग का उपयोग किया जाता है।

यह प्रभावी रूप से सन बग ट्रैकर में शर्मनाक प्राचीन बग रिपोर्ट को हल करता है जिसने इस तरह के एक समारोह के लिए कहा था।


35

यह अमरूद लाइब्रेरी की Files.createTempDir () का सोर्स कोड है। यह उतना ही जटिल है जितना कि आप सोच सकते हैं:

public static File createTempDir() {
  File baseDir = new File(System.getProperty("java.io.tmpdir"));
  String baseName = System.currentTimeMillis() + "-";

  for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
    File tempDir = new File(baseDir, baseName + counter);
    if (tempDir.mkdir()) {
      return tempDir;
    }
  }
  throw new IllegalStateException("Failed to create directory within "
      + TEMP_DIR_ATTEMPTS + " attempts (tried "
      + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')');
}

डिफ़ॉल्ट रूप से:

private static final int TEMP_DIR_ATTEMPTS = 10000;

यहाँ देखें


28

deleteOnExit()यदि आप स्पष्ट रूप से इसे बाद में हटाते हैं तो भी इसका उपयोग न करें ।

अधिक जानकारी के लिए Google 'deleteonexit बुराई है' , लेकिन समस्या का सार है:

  1. deleteOnExit() केवल सामान्य JVM शटडाउन के लिए हटाता है, JVM प्रक्रिया को क्रैश या नहीं मारता है।

  2. deleteOnExit() केवल JVM शटडाउन पर हटाता है - लंबे समय तक चलने वाली सर्वर प्रक्रियाओं के लिए अच्छा नहीं है क्योंकि:

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


1
हमारे पास एक JVM है जहाँ वर्ग और जार फ़ाइलों को JVM द्वारा बनाई गई छिपी हुई फ़ाइलें मिलती हैं, और इस अतिरिक्त जानकारी को हटाने में काफी समय लगता है। जब WARs विस्फोट करने वाले वेब कंटेनरों पर गर्म रेडिप्लॉय्स करते हैं, तो JVM साक्षरता को खत्म होने के बाद साफ करने में मिनटों का समय लगा सकता है लेकिन कुछ घंटों तक चलने से पहले बाहर निकल सकता है।
थोरबजोरन रावन एंडरसन

20

जावा 1.7 के रूप में createTempDirectory(prefix, attrs)और createTempDirectory(dir, prefix, attrs)में शामिल हैंjava.nio.file.Files

उदाहरण: File tempDir = Files.createTempDirectory("foobar").toFile();


14

यह वही है जो मैंने अपने कोड के लिए करने का फैसला किया है:

/**
 * Create a new temporary directory. Use something like
 * {@link #recursiveDelete(File)} to clean this directory up since it isn't
 * deleted automatically
 * @return  the new directory
 * @throws IOException if there is an error creating the temporary directory
 */
public static File createTempDir() throws IOException
{
    final File sysTempDir = new File(System.getProperty("java.io.tmpdir"));
    File newTempDir;
    final int maxAttempts = 9;
    int attemptCount = 0;
    do
    {
        attemptCount++;
        if(attemptCount > maxAttempts)
        {
            throw new IOException(
                    "The highly improbable has occurred! Failed to " +
                    "create a unique temporary directory after " +
                    maxAttempts + " attempts.");
        }
        String dirName = UUID.randomUUID().toString();
        newTempDir = new File(sysTempDir, dirName);
    } while(newTempDir.exists());

    if(newTempDir.mkdirs())
    {
        return newTempDir;
    }
    else
    {
        throw new IOException(
                "Failed to create temp dir named " +
                newTempDir.getAbsolutePath());
    }
}

/**
 * Recursively delete file or directory
 * @param fileOrDir
 *          the file or dir to delete
 * @return
 *          true iff all files are successfully deleted
 */
public static boolean recursiveDelete(File fileOrDir)
{
    if(fileOrDir.isDirectory())
    {
        // recursively delete contents
        for(File innerFile: fileOrDir.listFiles())
        {
            if(!FileUtilities.recursiveDelete(innerFile))
            {
                return false;
            }
        }
    }

    return fileOrDir.delete();
}

2
यह असुरक्षित है। पहले (समान रूप से असुरक्षित) विकल्प में जोकिम सॉयर की टिप्पणी देखें। फ़ाइल या डायर के अस्तित्व की जाँच करने के लिए और फ़ाइलनाम को हथियाने के लिए उचित तरीका, फ़ाइल या डीआईआर बनाकर है।
zbyszek

1
@zbyszek javadocs का कहना है कि "UUID एक क्रिप्टोग्राफिक रूप से मजबूत छद्म यादृच्छिक राउटर जनरेटर का उपयोग करके उत्पन्न होता है।" यह देखते हुए कि दुर्भावनापूर्ण प्रक्रिया कैसे मौजूद है (और mkdirs () के बीच एक ही नाम के साथ एक dir बनाता है) वास्तव में इसे देखकर अब मुझे लगता है कि मेरा अस्तित्व () परीक्षण थोड़ा मूर्खतापूर्ण हो सकता है।
कीथ

कीथ: UUID सुरक्षित है या नहीं इस मामले में महत्वपूर्ण नहीं है। यह उस नाम के बारे में जानकारी के लिए पर्याप्त है जो आपने किसी भी तरह "लीक" होने के लिए कहा था। उदाहरण के लिए, मान लें कि बनाई जा रही फ़ाइल NFS फाइल सिस्टम पर है, और हमलावर पैकेट को सुन सकता है (निष्क्रिय)। या यादृच्छिक जनरेटर राज्य को लीक कर दिया गया है। अपनी टिप्पणी में मैंने कहा कि आपका समाधान उतना ही असुरक्षित है जितना कि स्वीकृत उत्तर, लेकिन यह उचित नहीं है: स्वीकार किए गए व्यक्ति को औचित्य के साथ हारने के लिए तुच्छ है, और यह हार के लिए बहुत कठिन है। फिर भी, कुछ परिदृश्यों में यह निश्चित रूप से संभव है।
zbyszek

2
मैंने एक ही सोचा था और इस तरह से यादृच्छिक यूयूआईडीएस बिट का उपयोग करके एक समाधान लागू किया। कोई जांच मौजूद नहीं है, रैंडम यूआईडी विधि द्वारा इस्तेमाल किया जाने वाला मजबूत आरएनजी बनाने का सिर्फ एक प्रयास बहुत ज्यादा बिना किसी टक्कर की गारंटी देता है (डीबी तालिकाओं में प्राथमिक कुंजी उत्पन्न करने के लिए इस्तेमाल किया जा सकता है, यह खुद किया है और कभी टकराव नहीं जाना जाता है), इसलिए बहुत आत्मविश्वास से। अगर किसी को यकीन नहीं है, तो stackoverflow.com/questions/2513573/…
brabster

यदि आप जावा के कार्यान्वयन को देखते हैं, तो वे केवल यादृच्छिक नाम उत्पन्न करते हैं जब तक कि कोई टक्कर न हो। उनके अधिकतम प्रयास अनंत हैं। इसलिए यदि कोई दुर्भावनापूर्ण आपकी फ़ाइल / निर्देशिका नाम का अनुमान लगाते रहे, तो यह हमेशा के लिए बंद हो जाएगा। यहाँ स्रोत का लिंक दिया गया है: hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/9fb81d7a2f16/src/share/ ... मैं सोच रहा था कि यह किसी भी तरह से फाइल सिस्टम को लॉक कर सकता है ताकि यह एटोमिकली एक अनोखा नाम उत्पन्न कर सके। निर्देशिका बनाएँ, लेकिन मुझे लगता है कि यह स्रोत कोड के अनुसार ऐसा नहीं करता है।
dosentmatter

5

खैर, "createTempFile" वास्तव में फ़ाइल बनाता है। तो क्यों न पहले इसे डिलीट किया जाए, और फिर इस पर mkdir किया जाए?


1
आपको हमेशा mkdir () के लिए रिटर्न वैल्यू की जांच करनी चाहिए। यदि वह गलत है तो इसका मतलब है कि निर्देशिका पहले से मौजूद है। यह सुरक्षा समस्याओं का कारण बन सकता है, इसलिए विचार करें कि क्या इससे आपके आवेदन में कोई त्रुटि हो सकती है या नहीं।
सेरेल बोथा

1
अन्य उत्तर में दौड़ की स्थिति के बारे में नोट देखें।
वोल्कर स्टोलज़

यह मुझे पसंद है, दौड़ को छोड़कर
मार्टिन विकमन

4

इस कोड को अच्छी तरह से काम करना चाहिए:

public static File createTempDir() {
    final String baseTempPath = System.getProperty("java.io.tmpdir");

    Random rand = new Random();
    int randomInt = 1 + rand.nextInt();

    File tempDir = new File(baseTempPath + File.separator + "tempDir" + randomInt);
    if (tempDir.exists() == false) {
        tempDir.mkdir();
    }

    tempDir.deleteOnExit();

    return tempDir;
}

3
क्या होगा यदि निर्देशिका पहले से मौजूद है और आपके पास इसे पढ़ने / लिखने की सुविधा नहीं है या क्या है अगर यह एक नियमित फ़ाइल है? आपकी वहां भी दौड़ की स्थिति है।
जेरेमी हुइस्कैम्प

2
इसके अलावा, deleteOnExit गैर-खाली निर्देशिकाओं को नहीं हटाएगा।
ट्रेंटन

3

जैसा कि चर्चा में है इस RFE और इसकी टिप्पणियों , आप tempDir.delete()पहले कॉल कर सकते हैं । या आप System.getProperty("java.io.tmpdir")वहां एक निर्देशिका का उपयोग कर सकते हैं और बना सकते हैं । किसी भी तरह से, आपको कॉल करने के लिए याद रखना चाहिए tempDir.deleteOnExit(), या आपके द्वारा किए जाने के बाद फ़ाइल को हटाया नहीं जाएगा।


क्या यह संपत्ति "java.io.tmpdir" नहीं है, न कि "... अस्थायी"? Java.sun.com/j2se/1.4.2/docs/api/java/io/File.html
एंड्रयू स्वान

निस्संदेह। मैंने जो पढ़ा है उसे दोहराने से पहले मुझे सत्यापित करना चाहिए था।
माइकल मायर्स

Java.io.tmpdir को साझा किया गया है, इसलिए आपको किसी अन्य पैर की उंगलियों पर कदम रखने से बचने के लिए सभी सामान्य वूडू करने की आवश्यकता है।
थोरबजोरन रावन एंडरसन

3

बस पूरा करने के लिए, यह Google अमरूद लाइब्रेरी का कोड है। यह मेरा कोड नहीं है, लेकिन मुझे लगता है कि इस धागे में इसे यहाँ दिखाना उचित है।

  /** Maximum loop count when creating temp directories. */
  private static final int TEMP_DIR_ATTEMPTS = 10000;

  /**
   * Atomically creates a new directory somewhere beneath the system's temporary directory (as
   * defined by the {@code java.io.tmpdir} system property), and returns its name.
   *
   * <p>Use this method instead of {@link File#createTempFile(String, String)} when you wish to
   * create a directory, not a regular file. A common pitfall is to call {@code createTempFile},
   * delete the file and create a directory in its place, but this leads a race condition which can
   * be exploited to create security vulnerabilities, especially when executable files are to be
   * written into the directory.
   *
   * <p>This method assumes that the temporary volume is writable, has free inodes and free blocks,
   * and that it will not be called thousands of times per second.
   *
   * @return the newly-created directory
   * @throws IllegalStateException if the directory could not be created
   */
  public static File createTempDir() {
    File baseDir = new File(System.getProperty("java.io.tmpdir"));
    String baseName = System.currentTimeMillis() + "-";

    for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
      File tempDir = new File(baseDir, baseName + counter);
      if (tempDir.mkdir()) {
        return tempDir;
      }
    }
    throw new IllegalStateException(
        "Failed to create directory within "
            + TEMP_DIR_ATTEMPTS
            + " attempts (tried "
            + baseName
            + "0 to "
            + baseName
            + (TEMP_DIR_ATTEMPTS - 1)
            + ')');
  }

2

मुझे वही समस्या मिली, इसलिए यह उन लोगों के लिए एक और जवाब है, जो रुचि रखते हैं, और यह उपरोक्त में से एक के समान है:

public static final String tempDir = System.getProperty("java.io.tmpdir")+"tmp"+System.nanoTime();
static {
    File f = new File(tempDir);
    if(!f.exists())
        f.mkdir();
}

और मेरे आवेदन के लिए, मैंने फैसला किया कि बाहर निकलने पर अस्थायी को खाली करने के लिए एक विकल्प में जोड़ने के लिए इसलिए मैंने एक शट-डाउन हुक में जोड़ा:

Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            //stackless deletion
            String root = MainWindow.tempDir;
            Stack<String> dirStack = new Stack<String>();
            dirStack.push(root);
            while(!dirStack.empty()) {
                String dir = dirStack.pop();
                File f = new File(dir);
                if(f.listFiles().length==0)
                    f.delete();
                else {
                    dirStack.push(dir);
                    for(File ff: f.listFiles()) {
                        if(ff.isFile())
                            ff.delete();
                        else if(ff.isDirectory())
                            dirStack.push(ff.getPath());
                    }
                }
            }
        }
    });

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


2

जैसा कि आप अन्य उत्तरों में देख सकते हैं, कोई मानक दृष्टिकोण उत्पन्न नहीं हुआ है। इसलिए आपने पहले ही अपाचे कॉमन्स का उल्लेख किया है, मैं अपाचे कॉमन्स आईओ से फाइल यूटिल्स का उपयोग करते हुए निम्नलिखित दृष्टिकोण प्रस्तावित करता हूं :

/**
 * Creates a temporary subdirectory in the standard temporary directory.
 * This will be automatically deleted upon exit.
 * 
 * @param prefix
 *            the prefix used to create the directory, completed by a
 *            current timestamp. Use for instance your application's name
 * @return the directory
 */
public static File createTempDirectory(String prefix) {

    final File tmp = new File(FileUtils.getTempDirectory().getAbsolutePath()
            + "/" + prefix + System.currentTimeMillis());
    tmp.mkdir();
    Runtime.getRuntime().addShutdownHook(new Thread() {

        @Override
        public void run() {

            try {
                FileUtils.deleteDirectory(tmp);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
    return tmp;

}

यह पसंद किया जाता है क्योंकि अपाचे पुस्तकालय को कहा जाता है जो पूछे गए "मानक" के सबसे करीब आता है और जेडीके 7 और पुराने संस्करणों के साथ काम करता है। यह एक "पुरानी" फ़ाइल उदाहरण (जो कि स्ट्रीम आधारित है) देता है और "नया" पथ उदाहरण नहीं है (जो कि बफर आधारित है और यह JDK7 के getTemporaryDirectory () विधि) का परिणाम होगा -> इसलिए यह वह रिटर्न देता है जो लोगों को तब चाहिए जब वे एक अस्थायी निर्देशिका बनाना चाहते हैं।


1

मुझे एक अद्वितीय नाम बनाने के कई प्रयास पसंद हैं, लेकिन यहां तक ​​कि यह समाधान एक दौड़ की स्थिति से इंकार नहीं करता है। एक और प्रक्रिया परीक्षण के लिए exists()और if(newTempDir.mkdirs())विधि मंगलाचरण के बाद फिसल सकती है । मुझे पता नहीं है कि मूल कोड का उपयोग किए बिना इसे पूरी तरह से सुरक्षित कैसे बनाया जाए, जो मुझे लगता है कि अंदर दफन है File.createTempFile()


1

जावा 7 से पहले आप भी कर सकते हैं:

File folder = File.createTempFile("testFileUtils", ""); // no suffix
folder.delete();
folder.mkdirs();
folder.deleteOnExit();

1
अच्छा कोड है। लेकिन unfortunatelly "deleteOnExit ()" काम नहीं करेगा, क्योंकि जावा एक बार में पूरे फ़ोल्डर को नहीं हटा सकता है। आपको सभी फ़ाइलों को पुनरावर्ती रूप से हटाना होगा: /
एडम टारस

1

इस छोटे से उदाहरण का प्रयास करें:

कोड:

try {
    Path tmpDir = Files.createTempDirectory("tmpDir");
    System.out.println(tmpDir.toString());
    Files.delete(tmpDir);
} catch (IOException e) {
    e.printStackTrace();
}


आयात:
java.io.IOException
java.nio.file.Files
java.nio.file.Path

Windows मशीन पर कंसोल आउटपुट:
C: \ Users \ userName \ AppData \ Local \ Temp \ tmpDir2908538301081367877

टिप्पणी:
Files.createTempDirectory अनूठे तरीके से अद्वितीय आईडी बनाती है - 2908538301081367877।

नोट:
निर्देशिकाओं को पुन: हटाने के लिए निम्नलिखित पढ़ें:
जावा में पुनरावर्ती रूप से निर्देशिकाएं हटाएं


0

का उपयोग करना File#createTempFileऔर deleteनिर्देशिका के लिए एक विशिष्ट नाम बनाना ठीक लगता है। आपको ShutdownHookJVM शटडाउन पर निर्देशिका (पुनरावर्ती) को हटाने के लिए एक जोड़ना चाहिए ।


एक शटडाउन हुक बोझिल है। फ़ाइल नहीं हटाई जाएगी # हटाएं काम?
डेनियल हिलर

2
#deleteOnExit ने मेरे लिए काम नहीं किया - मेरा मानना ​​है कि यह गैर-रिक्त निर्देशिकाओं को नहीं हटाएगा।
मुरिलुक

मैंने जावा 8 के साथ एक त्वरित परीक्षण लागू किया, लेकिन अस्थायी फ़ोल्डर को हटाया नहीं गया, देखें pastebin.com/mjgG70KG
geri
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.