জাভাতে অস্থায়ী ডিরেক্টরি / ফোল্ডার কীভাবে তৈরি করবেন?


364

জাভা অ্যাপ্লিকেশনের অভ্যন্তরে কোনও অস্থায়ী ডিরেক্টরি তৈরি করার কোনও মানক এবং নির্ভরযোগ্য উপায় আছে? আছে জাভার ইস্যু ডাটাবেসের মধ্যে একটি এন্ট্রি , যা মন্তব্য কোডের একটি বিট আছে, কিন্তু আমি ভাবছি যদি সেখানে একটি প্রমিত সমাধান স্বাভাবিক লাইব্রেরি (Apache, কমন্স ইত্যাদি) এক পাওয়া যাবে কি?

উত্তর:


390

আপনি যদি জেডিকে 7 ব্যবহার করছেন তবে অস্থায়ী ডিরেক্টরি তৈরি করতে নতুন ফাইলস.ক্রিটটেম্প ডিরেক্টরি ডিরেক্টরিটি ব্যবহার করুন class

Path tempDirWithPrefix = Files.createTempDirectory(prefix);

জেডিকে Before এর আগে এটি করা উচিত:

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

আপনি চাইলে আপনি আরও ভাল ব্যতিক্রম করতে পারেন (সাবক্লাস আইওএক্সেপশন)।


12
এটা বিপজ্জনক. জাভা ফাইলগুলি তাত্ক্ষণিকভাবে মুছে ফেলা না হিসাবে জানা যায়, তাই
এমকেডির

4
@ ডেমির্গ একটি ফাইল তত্ক্ষণাত মুছে ফেলা না হওয়ার ঘটনাটি উইন্ডোজে যখন ফাইলটি ইতিমধ্যে খোলা থাকে (উদাহরণস্বরূপ এটি কোনও ভাইরাস স্ক্যানার দ্বারা খোলা হতে পারে)। অন্যথায় প্রদর্শন করার জন্য আপনার কাছে অন্য ডকুমেন্টেশন রয়েছে (আমি এই জাতীয় জিনিসের বিষয়ে আগ্রহী :-)? যদি এটি নিয়মিত ঘটে থাকে তবে উপরের কোডটি কাজ করবে না, যদি এটি বিরল হয় তবে মুছুন না হওয়া পর্যন্ত উপরের কোডটিতে কলটি ল্যাপিং (বা কিছু সর্বাধিক চেষ্টা করার চেষ্টা করা) কাজ করবে।
তোফুবিয়ার

6
@ ডেমির্গ জাভা ফাইলগুলি তাত্ক্ষণিকভাবে মোছার জন্য নয়। এটি সত্য, আপনি এটি না খুললেও। সুতরাং, আরও নিরাপদ উপায় temp.delete(); temp = new File(temp.getPath + ".d"); temp.mkdir(); ..., temp.delete();
Xiè Jìléi

102
এই কোডটির মধ্যে delete()এবং এর মধ্যে একটি রেসের শর্ত রয়েছে mkdir(): একটি বিদ্বেষপূর্ণ প্রক্রিয়া ইতিমধ্যে টার্গেট ডিরেক্টরি তৈরি করতে পারে (সম্প্রতি তৈরি ফাইলটির নাম গ্রহণ করে)। দেখুন Files.createTempDir()একটি বিকল্প জন্য।
জোছিম সউর

11
আমি পছন্দ করি! দাঁড়িয়ে থাকা, এটি খুব সহজে মিস করা। আমি শিক্ষার্থীদের দ্বারা লিখিত প্রচুর কোড পড়েছি ... যদি (! I) বিরক্তিকর হওয়ার পক্ষে সাধারণ হয় :-)
তোফুবিয়ার

182

গুগল পেয়ারা লাইব্রেরিতে প্রচুর সহায়ক ইউটিলিটি রয়েছে। এখানে নোটের মধ্যে একটি ফাইল ক্লাস । এটি সহ অনেকগুলি কার্যকর পদ্ধতি রয়েছে:

File myTempDir = Files.createTempDir();

এটি এক লাইনে আপনি যা চেয়েছিলেন ঠিক তা করে। আপনি যদি এখানে ডকুমেন্টেশনটি পড়েন তবে আপনি দেখতে পাবেন যে প্রস্তাবিত অভিযোজনটি File.createTempFile("install", "dir")সাধারণত নিরাপত্তা দুর্বলতার পরিচয় দেয়।


আমি ভাবছি আপনি কী দুর্বলতার কথা উল্লেখ করেছেন। এই পদ্ধতির কোনও রেস শর্ত তৈরিরূপে উপস্থিত হয় না কারণ ফাইল mmkdir () যদি এই জাতীয় ডিরেক্টরি ইতিমধ্যে উপস্থিত থাকে (আক্রমণকারী দ্বারা তৈরি করা হয়) ব্যর্থ হতে পারে। আমি মনে করি না যে এই কলটি কোনও দূষিত সিমলিংকের মাধ্যমে অনুসরণ করবে। আপনি কি বলতে চেয়েছেন তা কি স্পষ্ট করে বলতে পারেন?
এবিবি

3
@ আবাব: পেয়ারা ডকুমেন্টেশনে বর্ণিত অবস্থার বিবরণ আমি জানি না। আমি সন্দেহ করি যে ডকুমেন্টেশনটি সঠিকভাবে দেওয়া হয়েছে যে এটি বিশেষত সমস্যাটি ডেকে আনে।
স্পিনা 21

1
@bb ঠিক বলেছেন যতক্ষণ না এমকিডির () এর রিটার্ন চেক করা থাকে ততক্ষণ এটি সুরক্ষিত থাকবে। কোড স্পাইনা এই এমকেডির () পদ্ধতিটি ব্যবহার করার জন্য নির্দেশ করে। grepcode.com/file/repo1.maven.org/maven2/com.google.guava/guava/… । / Tmp ডিরেক্টরি ব্যবহার করার সময় এটি ইউনিক্স সিস্টেমে কেবলমাত্র একটি সম্ভাব্য সমস্যা কারণ এটিতে স্টিকি বিট সক্ষম রয়েছে।
সারেল বোথা

@ শেরেলবোথা এখানে শূন্যস্থান পূরণ করার জন্য ধন্যবাদ। আমি বেশ কিছুক্ষণ ধরে এই সম্পর্কে অবাক হয়ে ভাবছিলাম।
স্পিনা

168

যদি আপনার পরীক্ষার জন্য অস্থায়ী ডিরেক্টরি প্রয়োজন হয় এবং আপনি jUnit ব্যবহার করছেন, @Ruleএকসাথে TemporaryFolderআপনার সমস্যা সমাধান করে:

@Rule
public TemporaryFolder folder = new TemporaryFolder();

ডকুমেন্টেশন থেকে :

টেম্পোরারিফোল্ডার বিধি পরীক্ষার পদ্ধতি শেষ হওয়ার পরে মুছে ফেলার গ্যারান্টিযুক্ত ফাইল এবং ফোল্ডার তৈরি করতে দেয় (এটি পাস হয় বা ব্যর্থ হয়)


হালনাগাদ:

আপনি যদি জুনিত বৃহস্পতি (সংস্করণ 5.1.1 বা তার বেশি) ব্যবহার করছেন তবে আপনার কাছে জুনিট পাইওনিয়ার ব্যবহার করার বিকল্প রয়েছে যা জুনিত 5 এক্সটেনশন প্যাক।

প্রকল্পের নথি থেকে অনুলিপি করা :

উদাহরণস্বরূপ, নিম্নলিখিত পরীক্ষাগুলি একক পরীক্ষার পদ্ধতির জন্য এক্সটেনশানটিকে নিবন্ধভুক্ত করে, অস্থায়ী ডিরেক্টরিতে একটি ফাইল তৈরি করে এবং লেখায় এবং এর সামগ্রীটি পরীক্ষা করে।

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

আরো তথ্য JavaDoc এবং TempDirectory এর JavaDoc

Gradle:

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

ম্যাভেন:

<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 থেকে পাওয়া
এডুয়ার্ড ভার্চ

উইন্ডোজ on-এ জুনিত ৪.৮.২ এ কাজ করে না! (অনুমতি ইস্যু)
ব্যতিক্রম

2
@ ক্রেইগ্রারঞ্জার: কেন এটার উপর নির্ভর করা বুদ্ধিমানের কাজ?
অ্যাডাম পার্কিন 21

2
@ অ্যাডাম পারকিন সত্যই, আমার আর মনে নেই। ব্যাখ্যা ব্যর্থ!
ক্রেগ রিঞ্জার

1
এই পদ্ধতির মূল সুবিধা হ'ল ডিরেক্টরিটি ইউএনইটি দ্বারা পরিচালিত হয় (পরীক্ষার আগে তৈরি হয়েছিল এবং পরীক্ষার পরে পুনরাবৃত্তভাবে মোছা হয়)। এবং এটি কাজ করে। আপনি যদি "টেম্প দির এখনও তৈরি করেননি" পান তবে এটি হতে পারে কারণ আপনি @ বিধি বা ক্ষেত্রটিকে জনসাধারণের মধ্যে ভুলে গেছেন।
বোগদান কলম্যাক

42

এই সমস্যাটি সমাধান করার জন্য নিখরচায় লিখিত কোড বর্ণের শর্তের সাথে ভুগছে, এখানে বেশ কয়েকটি উত্তর রয়েছে। Icallyতিহাসিকভাবে আপনি জাতির পরিস্থিতি সম্পর্কে সাবধানতার সাথে চিন্তা করতে পারেন এবং নিজেই এটি লিখতে পারেন, বা আপনি গুগলের পেয়ারা (স্পিনার উত্তর হিসাবে প্রস্তাবিত like

তবে জেডিকে of এর মতো সুসংবাদ রয়েছে! জাভা স্ট্যান্ডার্ড লাইব্রেরি নিজেই এখন এই সমস্যার যথাযথভাবে কার্যকর (অ-বর্ণবাদী) সমাধান সরবরাহ করে। আপনি java.nio.file.Files চান # createTempDirectory ()ডকুমেন্টেশন থেকে :

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

প্রদত্ত উপসর্গটির নাম উত্পাদন করতে ব্যবহার করে নির্দিষ্ট ডিরেক্টরিতে একটি নতুন ডিরেক্টরি তৈরি করে। ফলস্বরূপ পাথটি প্রদত্ত ডিরেক্টরি হিসাবে একই ফাইলসিস্টেমের সাথে সম্পর্কিত।

ডিরেক্টরিটির নাম কীভাবে নির্মিত হয় তা বিশদ বাস্তবায়ন নির্ভর এবং তাই নির্দিষ্ট করা হয়নি। যেখানে সম্ভাব্য উপসর্গটি প্রার্থীদের নাম তৈরি করতে ব্যবহৃত হয়।

এটি কার্যকরভাবে সান বাগ ট্র্যাকারে বিব্রতকরভাবে প্রাচীন বাগ রিপোর্টটি সমাধান করে যা ঠিক যেমন একটি ফাংশন চেয়েছিল।


35

এটি পেয়ারা লাইব্রেরির ফাইলসক্রেটটেম্পডির () এর উত্স কোড। এটি যতটা জটিল আপনি ভাবেন তেমন জটিল নয়:

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()আপনি পরে স্পষ্টভাবে মুছলেও ব্যবহার করবেন না ।

আরও তথ্যের জন্য গুগল 'ডিলিটোনেক্সিট অশুভ' , তবে সমস্যার সূত্রটি হ'ল:

  1. deleteOnExit() কেবলমাত্র জেভিএম শাটডাউনের জন্য মুছে ফেলা হয়, জেভিএম প্রক্রিয়া ক্র্যাশ বা হত্যা না করে।

  2. deleteOnExit() কেবল জেভিএম শাটডাউনে মুছে ফেলা - দীর্ঘ চলমান সার্ভার প্রক্রিয়াগুলির জন্য ভাল নয় কারণ:

  3. সবচেয়ে খারাপ - deleteOnExit()প্রতিটি অস্থায়ী ফাইল এন্ট্রি জন্য মেমরি গ্রহণ। যদি আপনার প্রক্রিয়া কয়েক মাস ধরে চলতে থাকে বা অল্প সময়ের মধ্যে প্রচুর টেম্প ফাইল তৈরি করে, আপনি মেমরিটি গ্রাস করেন এবং জেভিএম বন্ধ না হওয়া পর্যন্ত এটিকে কখনই প্রকাশ করবেন না।


1
আমাদের একটি জেভিএম রয়েছে যেখানে ক্লাস এবং জার ফাইলগুলি জেভিএমের তৈরি নীচে লুকানো ফাইলগুলি পায় এবং এই অতিরিক্ত তথ্য মুছতে বেশ খানিকটা সময় নেয়। যুদ্ধের বিস্ফোরিত ওয়েব ধারকগুলিতে গরম পুনর্নির্মাণগুলি করার সময়, জেভিএম শেষ হওয়ার পরে পরিষ্কার হতে কয়েক মিনিট সময় নিতে পারে তবে কয়েক ঘন্টা চালিয়ে যাওয়ার পরে বেরিয়ে আসার আগে।
থোরবজর্ন রাভন অ্যান্ডারসন

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

2
আমি একই চিন্তা করেছি এবং এর মতো এলোমেলো ইউআইইডি ব্যবহার করে একটি সমাধান কার্যকর করেছি। অস্তিত্বের জন্য কোনও চেক নেই, তৈরির জন্য কেবল একটি প্রচেষ্টা - র্যান্ডম ইউইউডি পদ্ধতি দ্বারা ব্যবহৃত শক্তিশালী আরএনজি প্রায় কোনও সংঘর্ষের নিশ্চয়তা দেয় না (ডিবি টেবিলগুলিতে প্রাথমিক কী তৈরি করতে ব্যবহার করা যেতে পারে, এটি নিজেই করেছিলেন এবং কখনও সংঘর্ষের মুখোমুখি হতে পারেন না), তাই যথেষ্ট আত্মবিশ্বাসী। যে কেউ নিশ্চিত না থাকলে, খুঁজে বার করো stackoverflow.com/questions/2513573/...
brabster

আপনি যদি জাভাটির বাস্তবায়নের দিকে লক্ষ্য করেন তবে কোনও সংঘর্ষ না হওয়ার আগ পর্যন্ত এগুলি কেবল এলোমেলো নাম উত্পন্ন করে। তাদের সর্বাধিক প্রচেষ্টা অসীম। সুতরাং যদি কোনও দূষিত ব্যক্তি আপনার ফাইল / ডিরেক্টরি নামটি অনুমান করতে থাকে তবে তা চিরতরে লুপ হয়ে যায়। এখানে উত্সটির একটি লিঙ্ক দেওয়া হয়েছে: hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/9fb81d7a2f16/src/share/… আমি ভাবছিলাম যে এটি কোনওভাবে লক করতে পারে যাতে এটি পরমাণুভাবে একটি অনন্য নাম তৈরি করতে পারে এবং ডিরেক্টরি তৈরি করুন, তবে আমার ধারণা এটি উত্স কোড অনুসারে এটি করে না।
dosentmatter

5

ঠিক আছে, "ক্রিয়েটেম্পফিল" আসলে ফাইলটি তৈরি করে। সুতরাং কেন এটি প্রথমে মুছে ফেলবেন না, এবং তারপরে এমকিডিরটি করবেন না কেন?


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
এছাড়াও, মুছে ফেলুনঅ্যাক্সিট খালি নয় এমন ডিরেক্টরি মুছবে না।
ট্রেনটন

3

এই আরএফই এবং এর মন্তব্যে যেমন আলোচনা হয়েছে , আপনি 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

কেবলমাত্র সমাপ্তির জন্য, এটি গুগল পেয়ারা লাইব্রেরির কোড। এটি আমার কোড নয়, তবে আমি মনে করি এটি এখানে এই থ্রেডে দেখানো মূল্যবান।

  /** 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());
                    }
                }
            }
        }
    });

কলটিস্ট্যাকটি ব্যবহার না করে পদ্ধতিটি টেম্প মোছার আগে সমস্ত সাবডিয়ার এবং ফাইল মুছে ফেলে (যা পুরোপুরি alচ্ছিক এবং আপনি এটি এই সময়ে পুনরাবৃত্তি দিয়ে করতে পারেন), তবে আমি নিরাপদ দিকে থাকতে চাই।


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 এবং পুরানো সংস্করণ উভয়ই নিয়ে কাজ করে এমন পাঠাগারটি কমোন করার জন্য এটি পছন্দ করা হয়। এটি একটি "পুরাতন" ফাইলের উদাহরণও দেয় (যা স্ট্রিম ভিত্তিক) যা কোনও "নতুন" পথের উদাহরণ নয় (যা বাফার ভিত্তিক এবং জেডিকে 7 এর getTemporaryDirectory () পদ্ধতির ফলাফল) -> সুতরাং এটি বেশিরভাগ লোকের যা প্রয়োজন তা ফেরত দেয় তারা একটি অস্থায়ী ডিরেক্টরি তৈরি করতে চায়।


1

আমি একটি অনন্য নাম তৈরির একাধিক প্রচেষ্টা পছন্দ করি তবে এই সমাধানটি কোনও রেসের শর্তকে অস্বীকার করে না। পরীক্ষার জন্য পদ্ধতি exists()এবং if(newTempDir.mkdirs())প্রার্থনার পরে আরও একটি প্রক্রিয়া পিছলে যেতে পারে । নেটিভ কোডটি অবলম্বন না করে কীভাবে এটিকে পুরোপুরি সুরক্ষিত করা যায় সে সম্পর্কে আমার কোনও ধারণা নেই, যা আমি অনুমান করি যে এটি ভিতরে পুঁতে রয়েছে File.createTempFile()


1

জাভা 7 এর আগে আপনিও করতে পারেন:

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

1
চমৎকার কোড। তবে দুর্ভাগ্যক্রমে "মুছে ফেলা" -অনেক্সট () "কাজ করবে না, যেহেতু জাভা পুরো ফোল্ডারটি একবারে মুছতে পারে না। আপনাকে সমস্ত ফাইলগুলি পুনরাবৃত্তভাবে মুছতে হবে: /
অ্যাডাম তারাস

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

উইন্ডোজ মেশিনে কনসোল আউটপুট:
সি: \ ব্যবহারকারীগণের ব্যবহারকারী নাম \ অ্যাপডাটা \ স্থানীয় \ টেম্প \ tmpDir2908538301081367877

মন্তব্য:
ফাইলস.ক্রিয়েটেম্প ডিরেক্টরিটি অনন্যভাবে আইডি উত্পন্ন করে - 2908538301081367877.

দ্রষ্টব্য:
ডিরেক্টরিগুলি পুনরাবৃত্তভাবে মোছার জন্য নিম্নলিখিতটি পড়ুন:
জাভাতে পুনরাবৃত্তভাবে ডিরেক্টরিগুলি মুছুন


0

ডিরেক্টরিটির জন্য একটি অনন্য নাম ব্যবহার করা File#createTempFileএবং deleteতৈরি করা ঠিক আছে বলে মনে হচ্ছে। আপনার ShutdownHookজেভিএম শাটডাউন ডিরেক্টরিটি পুনরাবৃত্ত করতে মুছে ফেলার জন্য একটি যুক্ত করা উচিত ।


একটি শাটডাউন হুক জটিল। ফাইল # ডিলিটঅনএক্সিটও কাজ করবে না?
ড্যানিয়েল হিলার

2
#deleteOnExit আমার পক্ষে কাজ করেনি - আমি বিশ্বাস করি এটি খালি নয় এমন ডিরেক্টরি মুছবে না।
মুরিলোক

আমি জাভা 8 দিয়ে একটি দ্রুত পরীক্ষা চালিয়েছি, তবে অস্থায়ী ফোল্ডারটি মোছা হয়নি, পেস্টবিন.com
mjgG70KG
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.