是否有一种在Java应用程序中创建临时目录的标准而可靠的方法?在Java的问题数据库中有一个条目,在评论中有一些代码,但我想知道在一个常用的库(Apache Commons等)中是否有一个标准的解决方案?
当前回答
正如本RFE及其注释中所讨论的,您可以首先调用tempDir.delete()。或者你可以使用System.getProperty("java.io.tmpdir")并在那里创建一个目录。无论采用哪种方法,都应该记得调用tempDir.deleteOnExit(),否则在完成操作后文件将不会被删除。
其他回答
我也遇到了同样的问题,所以这只是给那些感兴趣的人的另一个答案,它类似于上面的一个:
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());
}
}
}
}
});
该方法在删除临时文件之前删除所有subdirs和文件,而不使用callstack(这完全是可选的,此时您可以使用递归来完成),但我想安全起见。
只是为了完成,这是谷歌番石榴库的代码。这不是我的代码,但我认为在这个线程中展示它是有价值的。
/** 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)
+ ')');
}
从Java 1.7开始,createTempDirectory(prefix, attrs)和createTempDirectory(dir, prefix, attrs)包含在Java .nio.file. files中
操作: 寺庙文件。
为解决这个问题而编写的天真代码会受到竞争条件的影响,包括这里的几个答案。从历史上看,您可以仔细考虑竞争条件并自己编写它,或者您可以使用第三方库,如谷歌的Guava(正如Spina的回答所建议的那样)。或者你可以编写有bug的代码。
但是对于JDK 7,有一个好消息!Java标准库本身现在为这个问题提供了一个正常工作的(非刺激性的)解决方案。你需要java.nio.file.Files#createTempDirectory()。从文档中可以看到:
public static Path createTempDirectory(Path dir,
String prefix,
FileAttribute<?>... attrs)
throws IOException
在指定目录中创建一个新目录,使用给定的前缀生成其名称。生成的Path与给定目录的相同文件系统相关联。
关于如何构造目录名称的详细信息取决于实现,因此没有指定。在可能的情况下,前缀用于构造候选名称。
这有效地解决了Sun bug跟踪器中要求这样一个功能的令人尴尬的古老bug报告。
即使稍后显式删除它,也不要使用deleteOnExit()。
谷歌'deleteonexit is evil'获取更多信息,但问题的要点是:
deleteOnExit()只删除正常的JVM关闭,不删除崩溃或杀死JVM进程。 deleteOnExit()只在JVM关闭时删除-不适合长时间运行的服务器进程,因为: 最糟糕的是deleteOnExit()为每个临时文件条目消耗内存。如果您的进程运行了几个月,或者在短时间内创建了大量临时文件,那么您将消耗内存,直到JVM关闭才释放内存。
推荐文章
- 到底是什么导致了堆栈溢出错误?
- 为什么Android工作室说“等待调试器”如果我不调试?
- Java:路径vs文件
- ExecutorService,如何等待所有任务完成
- Maven依赖Servlet 3.0 API?
- 如何在IntelliJ IDEA中添加目录到应用程序运行概要文件中的类路径?
- getter和setter是糟糕的设计吗?相互矛盾的建议
- Android room persistent: AppDatabase_Impl不存在
- Java的String[]在Kotlin中等价于什么?
- Intellij IDEA上的System.out.println()快捷方式
- 使用Spring RestTemplate获取JSON对象列表
- Spring JPA选择特定的列
- URLEncoder不能翻译空格字符
- Java中的super()
- 如何转换JSON字符串映射<字符串,字符串>与杰克逊JSON