Jeśli używasz JDK 7, użyj nowej klasy Files.createTempDirectory, aby utworzyć katalog tymczasowy.
Path tempDirWithPrefix = Files.createTempDirectory(prefix);
Przed JDK 7 powinno to zrobić:
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);
}
Możesz zrobić lepsze wyjątki (podklasa IOException), jeśli chcesz.
temp.delete(); temp = new File(temp.getPath + ".d"); temp.mkdir(); ..., temp.delete();
.delete()
imkdir()
: W międzyczasie złośliwy proces może utworzyć katalog docelowy (przyjmując nazwę niedawno utworzonego pliku). SprawdźFiles.createTempDir()
alternatywę.Biblioteka Google Guava ma mnóstwo przydatnych narzędzi. Jedną z ważniejszych tutaj jest klasa Files . Ma wiele przydatnych metod, w tym:
Robi dokładnie to, o co prosiłeś w jednym wierszu. Jeśli przeczytasz tutaj dokumentację , zobaczysz, że proponowana adaptacja
File.createTempFile("install", "dir")
zwykle wprowadza luki w zabezpieczeniach.źródło
Jeśli potrzebujesz tymczasowego katalogu do testowania i używasz jUnit,
@Rule
razem zTemporaryFolder
rozwiązaniem problemu:Z dokumentacji :
Aktualizacja:
Jeśli używasz JUnit Jupiter (wersja 5.1.1 lub nowsza), możesz skorzystać z JUnit Pioneer, który jest pakietem rozszerzeń JUnit 5.
Skopiowano z dokumentacji projektu :
Więcej informacji w JavaDoc i JavaDoc w TempDirectory
Stopień:
Maven:
Aktualizacja 2:
@TempDir Adnotacja dodano do JUnit Jupiter 5.4.0 uwalniania jako funkcję doświadczalnej. Przykład skopiowany z Podręcznika użytkownika JUnit 5 :
źródło
Naiwnie napisany kod rozwiązujący ten problem cierpi z powodu warunków wyścigowych, w tym kilku odpowiedzi tutaj. Historycznie można było dokładnie przemyśleć warunki wyścigu i napisać je samodzielnie, lub użyć biblioteki innej firmy, takiej jak Google Guava (jak sugeruje odpowiedź Spiny). Możesz też napisać błędny kod.
Ale od JDK 7 są dobre wieści! Sama standardowa biblioteka Java zapewnia teraz poprawnie działające (nieratyczne) rozwiązanie tego problemu. Chcesz java.nio.file.Files # createTempDirectory () . Z dokumentacji :
To skutecznie rozwiązuje zawstydzająco starożytny raport o błędach w module śledzenia błędów Sun, który poprosił o taką właśnie funkcję.
źródło
To jest kod źródłowy Files.createTempDir biblioteki Guava. Nie jest to tak skomplikowane, jak mogłoby się wydawać:
Domyślnie:
Spójrz tutaj
źródło
Nie używaj,
deleteOnExit()
nawet jeśli później usuniesz go wyraźnie.Google „deleteonexit is evil”, aby uzyskać więcej informacji, ale sedno problemu to:
deleteOnExit()
usuwa tylko w przypadku normalnego zamykania JVM, nie powoduje awarii ani nie zabija procesu JVM.deleteOnExit()
usuwa tylko przy zamykaniu JVM - nie nadaje się do długotrwałych procesów serwera, ponieważ:Najbardziej zło ze wszystkich -
deleteOnExit()
zużywa pamięć dla każdego wpisu pliku tymczasowego. Jeśli proces trwa kilka miesięcy lub w krótkim czasie utworzysz wiele plików tymczasowych, zużywasz pamięć i nigdy jej nie zwalniasz, dopóki JVM nie wyłączy się.źródło
Od wersji Java 1.7
createTempDirectory(prefix, attrs)
icreateTempDirectory(dir, prefix, attrs)
są zawarte wjava.nio.file.Files
Przykład:
File tempDir = Files.createTempDirectory("foobar").toFile();
źródło
Oto, co postanowiłem zrobić dla własnego kodu:
źródło
Cóż, „createTempFile” faktycznie tworzy plik. Dlaczego więc najpierw go nie usunąć, a następnie wykonać na nim mkdir?
źródło
Ten kod powinien działać dość dobrze:
źródło
Jak omówiono w tym RFE i jego komentarzach, możesz zadzwonić jako
tempDir.delete()
pierwszy. Lub możesz użyćSystem.getProperty("java.io.tmpdir")
i utworzyć tam katalog. Tak czy inaczej, pamiętaj, aby zadzwonićtempDir.deleteOnExit()
, w przeciwnym razie plik nie zostanie usunięty po zakończeniu.źródło
Na zakończenie jest to kod z biblioteki Google guava. To nie jest mój kod, ale myślę, że warto go pokazać tutaj w tym wątku.
źródło
Mam ten sam problem, więc jest to kolejna odpowiedź dla zainteresowanych i jest podobna do jednej z powyższych:
W przypadku mojej aplikacji zdecydowałem, że dodam opcję wyczyszczenia temp przy wyjściu, więc dodałem hak zamykający:
Metoda usuwa wszystkie podkatalogi i pliki przed usunięciem temp , bez użycia stosu wywołań (który jest całkowicie opcjonalny i w tym momencie można to zrobić z rekurencją), ale chcę być po bezpiecznej stronie.
źródło
Jak widać w innych odpowiedziach, nie pojawiło się żadne standardowe podejście. Dlatego wspomniałeś już o Apache Commons, proponuję następujące podejście przy użyciu FileUtils z Apache Commons IO :
Jest to preferowane, ponieważ apache używa biblioteki, która jest jak najbliżej zadanego „standardu” i działa zarówno z JDK 7, jak i starszymi wersjami. Zwraca również „starą” instancję pliku (która jest oparta na strumieniu), a nie „nową” instancję ścieżki (która jest oparta na buforze i byłaby wynikiem metody getTemporaryDirectory () JDK7) -> Dlatego zwraca to, czego potrzebuje większość ludzi, gdy chcą utworzyć katalog tymczasowy.
źródło
Lubię wiele prób stworzenia unikalnej nazwy, ale nawet to rozwiązanie nie wyklucza warunków wyścigu. Kolejny proces może wślizgnąć się po teście
exists()
iif(newTempDir.mkdirs())
wywołaniu metody. Nie mam pojęcia, jak całkowicie uczynić to bezpiecznym bez uciekania się do natywnego kodu, który, jak przypuszczam, jest ukryty w środkuFile.createTempFile()
.źródło
Przed wersją Java 7 można również:
źródło
Spróbuj tego małego przykładu:
Kod:
Importuje:
java.io.IOException
java.nio.file.Files
java.nio.file.Path
Dane wyjściowe konsoli na komputerze z systemem Windows:
C: \ Users \ nazwa_użytkownika \ AppData \ Local \ Temp \ tmpDir2908538301081367877
Komentarz:
Files.createTempDirectory generuje unikatowy identyfikator atomatycznie - 2908538301081367877.
Uwaga:
Przeczytaj rekursywnie następujące katalogi:
Usuń katalogi rekurencyjnie w Javie
źródło
Używanie
File#createTempFile
idelete
do tworzenia unikalnej nazwy katalogu wydaje się być w porządku. Należy dodać a,ShutdownHook
aby usunąć katalog (rekurencyjnie) podczas zamykania JVM.źródło