临时目录是用于存储临时文件的目录。临时目录的位置依赖操作系统。在 Windows 中,临时目录通过 TEMP 环境变量定义,通常位置是 C:\Temp、%Windows%\Temp,或者根据每个用户放到 Local Settings\Temp。在 Linux/Unix 中,
全局临时目录在 /tmp 和 /var/tmp。
创建临时目录
NIO.2 提供了 createTempDirectory() 方法用于创建临时目录。这个方法会在系统默认临时目录位置创建临时目录。可以调用有两个参数的方法,第一个参数是临时目录命名前缀,可以为空,第二个可选参数是创建目录时设置的属性列表。下面的代码将创建两个临时目录,一个使用了前缀,另一个没有前缀:
class="java">String tmp_dir_prefix = "nio_";
try {
//passing null prefix
Path tmp_1 = Files.createTempDirectory(null);
System.out.println("TMP: " + tmp_1.toString());
//set a prefix
Path tmp_2 = Files.createTempDirectory(tmp_dir_prefix);
System.out.println("TMP: " + tmp_2.toString());
} catch (IOException e) {
System.err.println(e);
}
下面是在我机器上的输出结果:
TMP: C:\Users\Leo\AppData\Local\Temp\3238630399269555448
TMP: C:\Users\Leo\AppData\Local\Temp\nio_1097550355199661257
注:如果你不知道你的机器临时目录位置,可以使用下面的代码获取:
//output: C:\Users\Leo\AppData\Local\Temp\
String default_tmp = System.getProperty("java.io.tmpdir");
System.out.println(default_tmp);
也可以设置临时目录存放的位置,createTempDirectory() 方法除了前缀和属性列表外,还接受临时目录存放位置的 Path 对象。下面的代码演示了在 C:\rafaelnadal\tmp 目录下创建临时目录:
Path basedir = Filesystems.html" target="_blank">Systems.getDefault().getPath("C:/rafaelnadal/tmp/");
String tmp_dir_prefix = "rafa_";
…
try {
//create a tmp directory in the base dir
Path tmp = Files.createTempDirectory(basedir, tmp_dir_prefix);
System.out.println("TMP: " + tmp.toString());
} catch (IOException e) {
System.err.println(e);
}
可能的输出结果如下:
TMP: C:\rafaelnadal\tmp\rafa_1753327229539718259
使用 shutdown 钩子删除临时目录
大多数操作系统都可以自动删除临时目录(如果不可以,那么可以安装自动清理软件)。但是有的时候,
你需要以
编码的方式删除临时目录。为此,你可以使用 shutdown 钩子程序,这主要用于系统停止运行时进行资源清理和保存。这个钩子程序可以使用 Thread 类来实现,在
JVM 停止的时候会自动调用 run() 方法。
下面看看样例代码:
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Shutdown-hook activated ...");
//… here, cleanup/save resources
System.out.println("Shutdown-hook successfully executed ...");
}
});
利用钩子程序来删除临时目录是一个
比较好的选择。但是,目录在非空的情况下是不允许删除的,因此你需要
递归删除每一层的目录和文件。为了简单,我们这里的
例子只演示删除临时目录下只有临时文件和空的临时目录(大多数真实情况也是如此)。
下面的例子先创建了临时目录,然后利用 shutdown 钩子程序删除临时目录下的内容:
final Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp/");
final String tmp_dir_prefix = "rafa_";
try {
//create a tmp directory in the base dir
final Path tmp_dir = Files.createTempDirectory(basedir, tmp_dir_prefix);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Deleting the temporary folder ...");
try (DirectoryStream<Path> ds = Files.newDirectoryStream(tmp_dir)) {
for (Path file : ds) {
Files.delete(file);
}
Files.delete(tmp_dir);
} catch (IOException e) {
System.err.println(e);
}
System.out.println("Shutdown-hook completed...");
}
});
//simulate some I/O operations over the temporary file by sleeping 10 seconds
//when the time expires, the temporary file is deleted
Thread.sleep(10000);
//operations done
} catch (IOException | InterruptedException e) {
System.err.println(e);
}
注:上面的例子使用了 Thread.sleep() 方法来延长目录创建和 JVM 停止之间的时间,方便你进行观察整个创建和删除的过程。真实项目中,这里可以添加业务逻辑。
使用 deleteOnExit() 方法删除临时目录
另一个删除临时目录的方法是调用 File. deleteOnExit() 方法(非 NIO.2 的方法),这个方法会在 JVM 停止的时候删除文件或目录。因为这个方法会被每个临时目录和文件调用,那么将会占用很多
内存,因此被认为不是一个很好的选择。
注:如果你的系统将要长时间运行或创建了很多临时目录/文件或临时目录/文件只是很短暂的使用,那么使用 deleteOnExit() 就是一个比较差的选择。这个方法会一直占用内存,并且不会释放,直到 JVM 停止。
下面的代码演示了如何使用 deleteOnExit():
Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp/");
String tmp_dir_prefix = "rafa_";
try {
//create a tmp directory in the base dir
Path tmp_dir = Files.createTempDirectory(basedir, tmp_dir_prefix);
File asFile = tmp_dir.toFile();
asFile.deleteOnExit();
//simulate some I/O operations over the temporary file by sleeping 10 seconds
//when the time expires, the temporary file is deleted
//EACH CREATED TEMPORARY ENTRY SHOULD BE REGISTERED FOR DELETE ON EXIT
Thread.sleep(10000);
//operations done
} catch (IOException | InterruptedException e) {
System.err.println(e);
}
注:因为 deleteOnExit() 方法只能在 File 类上调用,因此需要先将 Path 对象通过 Path.toFile() 方法转换为 File 对象。
创建临时文件
在 NIO.2 中,可以调用 createTempFile() 方法在默认临时目录创建临时文件。这个方法有三个参数:临时文件的前缀(可为 null),临时文件的后缀名(如果设置为 null,那么默认值是 .tmp),用于在创建临时文件时设置文件属性的可选参数。
下面的代码将创建两个临时文件,一个使用默认的前缀和后缀,一个使用指定的前缀和后缀:
String tmp_file_prefix = "rafa_";
String tmp_file_sufix=".txt";
try {
//passing null prefix/suffix
Path tmp_1 = Files.createTempFile(null,null);
System.out.println("TMP: " + tmp_1.toString());
//set a prefix and a suffix
Path tmp_2 = Files.createTempFile(tmp_file_prefix, tmp_file_sufix);
System.out.println("TMP: " + tmp_2.toString());
} catch (IOException e) {
System.err.println(e);
}
上面的代码将会在系统默认位置创建临时文件,运行后输出如下:
TMP: C:\Users\Leo\AppData\Local\Temp\6873427319542945524.tmp
TMP: C:\Users\Leo\AppData\Local\Temp\rafa_6168226983257408796.txt
你也可以在调用 createTempFile() 方法创建临时文件的时候指定临时文件所在的目录。这个方法除了前缀、后缀和可选的文件属性外,还接受一个 Path 类型的参数,用于指定临时目录位置。
下面的代码会将临时文件创建到 C:\rafaelnadal\tmp 目录中:
Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");
String tmp_file_prefix = "rafa_";
String tmp_file_sufix=".txt";
try {
Path tmp_3 = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);
System.out.println("TMP: " + tmp_3.toString());
} catch (IOException e) {
System.err.println(e);
}
运行后输出结果显示:
TMP: C:\rafaelnadal\tmp\rafa_512352743612949417.txt
使用 shutdown 钩子删除临时文件
和删除临时目录一样,也可以用 shutdown 机制删除文件,下面的例子会现在 C:\rafaelnadal\tmp 目录下创建临时文件,等待 10 秒钟后,JVM 停止运行并删除临时文件:
Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");
String tmp_file_prefix = "rafa_";
String tmp_file_sufix = ".txt";
try {
final Path tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Deleting the temporary file ...");
try {
Files.delete(tmp_file);
} catch (IOException e) {
System.err.println(e);
}
System.out.println("Shutdown hook completed...");
}
});
//simulate some I/O operations over the temporary file by sleeping 10 seconds
//when the time expires, the temporary file is deleted
Thread.sleep(10000);
//operations done
} catch (IOException | InterruptedException e) {
System.err.println(e);
}
使用 deleteOnExit() 方法删除临时文件
和删除临时目录一样,也可以调用 deleteOnExit() 方法删除临时文件。下面的例子会现在 C:\rafaelnadal\tmp 目录下创建临时文件,等待 10 秒钟后,JVM 停止运行并删除临时文件:
Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");
String tmp_file_prefix = "rafa_";
String tmp_file_sufix = ".txt";
try {
final Path tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);
File asFile = tmp_file.toFile();
asFile.deleteOnExit();
//simulate some I/O operations over the temporary file by sleeping 10 seconds
//when the time expires, the temporary file is deleted
Thread.sleep(10000);
//operations done
} catch (IOException | InterruptedException e) {
System.err.println(e);
}
通过 DELETE_ON_CLOSE 删除临时文件
还有一个巧妙的用法是使用 DELETE_ON_CLOSE 选项。正如它名字描述的一样,它会在文件流关闭的时候删除文件。例如,下面的代码会使用 createTempFile() 方法在 C:\rafaelnadal\tmp 目录下创建临时文件,并且使用 DELETE_ON_CLOSE 选项打开文件流,在文件流关闭的时候,文件会被删除。
Path basedir = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp");
String tmp_file_prefix = "rafa_";
String tmp_file_sufix = ".txt";
Path tmp_file = null;
try {
tmp_file = Files.createTempFile(basedir, tmp_file_prefix, tmp_file_sufix);
} catch (IOException e) {
System.err.println(e);
}
try (OutputStream outputStream = Files.newOutputStream(tmp_file,
StandardOpenOption.DELETE_ON_CLOSE);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {
//simulate some I/O operations over the temporary file by sleeping 10 seconds
//when the time expires, the temporary file is deleted
Thread.sleep(10000);
//operations done
} catch (IOException | InterruptedException e) {
System.err.println(e);
}
你也可以不通过 createTempFile() 方法来模拟创建临时文件,只需要定义
文件名,并使用 DELETE_ON_CLOSE 和 CREATE 选项联合创建文件流,如下所示:
String tmp_file_prefix = "rafa_";
String tmp_file_sufix = ".txt";
Path tmp_file = null;
tmp_file = FileSystems.getDefault().getPath("C:/rafaelnadal/tmp", tmp_file_prefix +
"temporary" + tmp_file_sufix);
try (OutputStream outputStream = Files.newOutputStream(tmp_file, StandardOpenOption.CREATE,
StandardOpenOption.DELETE_ON_CLOSE);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream))) {
//simulate some I/O operations over the temporary file by sleeping 10 seconds
//when the time expires, the temporary file is deleted
Thread.sleep(10000);
//operations done
} catch (IOException | InterruptedException e) {
System.err.println(e);
}
文章来源:http://www.aptusource.org/2014/04/nio-2-creating-temporary-directories-and-
files/