是否有一种在Java应用程序中创建临时目录的标准而可靠的方法?在Java的问题数据库中有一个条目,在评论中有一些代码,但我想知道在一个常用的库(Apache Commons等)中是否有一个标准的解决方案?
当前回答
如果您使用的是JDK 7,请使用新的Files。类创建临时目录。
Path tempDirWithPrefix = Files.createTempDirectory(prefix);
在JDK 7之前,应该这样做:
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);
}
如果你愿意,你可以创建更好的异常(子类IOException)。
其他回答
这是我决定为我自己的代码所做的:
/**
* 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();
}
如果你需要一个临时目录进行测试,并且你正在使用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));
}
即使稍后显式删除它,也不要使用deleteOnExit()。
谷歌'deleteonexit is evil'获取更多信息,但问题的要点是:
deleteOnExit()只删除正常的JVM关闭,不删除崩溃或杀死JVM进程。 deleteOnExit()只在JVM关闭时删除-不适合长时间运行的服务器进程,因为: 最糟糕的是deleteOnExit()为每个临时文件条目消耗内存。如果您的进程运行了几个月,或者在短时间内创建了大量临时文件,那么您将消耗内存,直到JVM关闭才释放内存。
使用file# createTempFile和delete为目录创建一个唯一的名称似乎是可以的。您应该添加一个ShutdownHook,以便在JVM关闭时(递归地)删除目录。
在Java 7之前,你还可以:
File folder = File.createTempFile("testFileUtils", ""); // no suffix
folder.delete();
folder.mkdirs();
folder.deleteOnExit();
推荐文章
- Eclipse调试器总是阻塞在ThreadPoolExecutor上,没有任何明显的异常,为什么?
- Java生成两个给定值之间的随机数
- 如何有效地从数组列表或字符串数组中删除所有空元素?
- 比较JUnit断言中的数组,简洁的内置方式?
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令