是否有一种在Java应用程序中创建临时目录的标准而可靠的方法?在Java的问题数据库中有一个条目,在评论中有一些代码,但我想知道在一个常用的库(Apache Commons等)中是否有一个标准的解决方案?


当前回答

这段代码应该可以很好地工作:

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

其他回答

createTempFile实际上创建了文件。那么为什么不先删除它,然后再对它执行mkdir呢?

使用file# createTempFile和delete为目录创建一个唯一的名称似乎是可以的。您应该添加一个ShutdownHook,以便在JVM关闭时(递归地)删除目录。

即使稍后显式删除它,也不要使用deleteOnExit()。

谷歌'deleteonexit is evil'获取更多信息,但问题的要点是:

deleteOnExit()只删除正常的JVM关闭,不删除崩溃或杀死JVM进程。 deleteOnExit()只在JVM关闭时删除-不适合长时间运行的服务器进程,因为: 最糟糕的是deleteOnExit()为每个临时文件条目消耗内存。如果您的进程运行了几个月,或者在短时间内创建了大量临时文件,那么您将消耗内存,直到JVM关闭才释放内存。

为解决这个问题而编写的天真代码会受到竞争条件的影响,包括这里的几个答案。从历史上看,您可以仔细考虑竞争条件并自己编写它,或者您可以使用第三方库,如谷歌的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报告。

正如您在其他答案中看到的,没有标准的方法出现。 因此你已经提到了Apache Commons,我建议使用Apache Commons IO中的FileUtils来实现以下方法:

/**
 * 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;

}

这是首选的,因为apache公共库是最接近所要求的“标准”的库,并且适用于JDK 7和旧版本。这也返回了一个“旧的”文件实例(基于流),而不是一个“新的”路径实例(基于缓冲区,将是JDK7的getTemporaryDirectory()方法的结果)->因此,当大多数人想要创建临时目录时,它返回了他们需要的东西。