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


当前回答

我也遇到了同样的问题,所以这只是给那些感兴趣的人的另一个答案,它类似于上面的一个:

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(这完全是可选的,此时您可以使用递归来完成),但我想安全起见。

其他回答

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

试试这个小例子:

代码:

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

备注: 文件。createTempDirectory自动生成唯一ID - 2908538301081367877。 注意: 阅读以下递归删除目录的方法: 在Java中递归地删除目录

正如本RFE及其注释中所讨论的,您可以首先调用tempDir.delete()。或者你可以使用System.getProperty("java.io.tmpdir")并在那里创建一个目录。无论采用哪种方法,都应该记得调用tempDir.deleteOnExit(),否则在完成操作后文件将不会被删除。

如果你需要一个临时目录进行测试,并且你正在使用jUnit, @Rule和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和TempDirectory的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 Jupiter 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));
}

在Java 7之前,你还可以:

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