[NIO.2] 第二十八篇 创建临时目录和文件
程序员文章站
2022-04-25 23:05:14
...
临时目录是用于存储临时文件的目录。临时目录的位置依赖操作系统。在 Windows 中,临时目录通过 TEMP 环境变量定义,通常位置是 C:\Temp、%Windows%\Temp,或者根据每个用户放到 Local Settings\Temp。在 Linux/Unix 中,全局临时目录在 /tmp 和 /var/tmp。
创建临时目录
NIO.2 提供了 createTempDirectory() 方法用于创建临时目录。这个方法会在系统默认临时目录位置创建临时目录。可以调用有两个参数的方法,第一个参数是临时目录命名前缀,可以为空,第二个可选参数是创建目录时设置的属性列表。下面的代码将创建两个临时目录,一个使用了前缀,另一个没有前缀:
下面是在我机器上的输出结果:
注:如果你不知道你的机器临时目录位置,可以使用下面的代码获取:
也可以设置临时目录存放的位置,createTempDirectory() 方法除了前缀和属性列表外,还接受临时目录存放位置的 Path 对象。下面的代码演示了在 C:\rafaelnadal\tmp 目录下创建临时目录:
可能的输出结果如下:
使用 shutdown 钩子删除临时目录
大多数操作系统都可以自动删除临时目录(如果不可以,那么可以安装自动清理软件)。但是有的时候,你需要以编码的方式删除临时目录。为此,你可以使用 shutdown 钩子程序,这主要用于系统停止运行时进行资源清理和保存。这个钩子程序可以使用 Thread 类来实现,在 JVM 停止的时候会自动调用 run() 方法。
下面看看样例代码:
利用钩子程序来删除临时目录是一个比较好的选择。但是,目录在非空的情况下是不允许删除的,因此你需要递归删除每一层的目录和文件。为了简单,我们这里的例子只演示删除临时目录下只有临时文件和空的临时目录(大多数真实情况也是如此)。
下面的例子先创建了临时目录,然后利用 shutdown 钩子程序删除临时目录下的内容:
注:上面的例子使用了 Thread.sleep() 方法来延长目录创建和 JVM 停止之间的时间,方便你进行观察整个创建和删除的过程。真实项目中,这里可以添加业务逻辑。
使用 deleteOnExit() 方法删除临时目录
另一个删除临时目录的方法是调用 File. deleteOnExit() 方法(非 NIO.2 的方法),这个方法会在 JVM 停止的时候删除文件或目录。因为这个方法会被每个临时目录和文件调用,那么将会占用很多内存,因此被认为不是一个很好的选择。
注:如果你的系统将要长时间运行或创建了很多临时目录/文件或临时目录/文件只是很短暂的使用,那么使用 deleteOnExit() 就是一个比较差的选择。这个方法会一直占用内存,并且不会释放,直到 JVM 停止。
下面的代码演示了如何使用 deleteOnExit():
注:因为 deleteOnExit() 方法只能在 File 类上调用,因此需要先将 Path 对象通过 Path.toFile() 方法转换为 File 对象。
创建临时文件
在 NIO.2 中,可以调用 createTempFile() 方法在默认临时目录创建临时文件。这个方法有三个参数:临时文件的前缀(可为 null),临时文件的后缀名(如果设置为 null,那么默认值是 .tmp),用于在创建临时文件时设置文件属性的可选参数。
下面的代码将创建两个临时文件,一个使用默认的前缀和后缀,一个使用指定的前缀和后缀:
上面的代码将会在系统默认位置创建临时文件,运行后输出如下:
你也可以在调用 createTempFile() 方法创建临时文件的时候指定临时文件所在的目录。这个方法除了前缀、后缀和可选的文件属性外,还接受一个 Path 类型的参数,用于指定临时目录位置。
下面的代码会将临时文件创建到 C:\rafaelnadal\tmp 目录中:
运行后输出结果显示:
使用 shutdown 钩子删除临时文件
和删除临时目录一样,也可以用 shutdown 机制删除文件,下面的例子会现在 C:\rafaelnadal\tmp 目录下创建临时文件,等待 10 秒钟后,JVM 停止运行并删除临时文件:
使用 deleteOnExit() 方法删除临时文件
和删除临时目录一样,也可以调用 deleteOnExit() 方法删除临时文件。下面的例子会现在 C:\rafaelnadal\tmp 目录下创建临时文件,等待 10 秒钟后,JVM 停止运行并删除临时文件:
通过 DELETE_ON_CLOSE 删除临时文件
还有一个巧妙的用法是使用 DELETE_ON_CLOSE 选项。正如它名字描述的一样,它会在文件流关闭的时候删除文件。例如,下面的代码会使用 createTempFile() 方法在 C:\rafaelnadal\tmp 目录下创建临时文件,并且使用 DELETE_ON_CLOSE 选项打开文件流,在文件流关闭的时候,文件会被删除。
你也可以不通过 createTempFile() 方法来模拟创建临时文件,只需要定义文件名,并使用 DELETE_ON_CLOSE 和 CREATE 选项联合创建文件流,如下所示:
文章来源:http://www.aptusource.org/2014/04/nio-2-creating-temporary-directories-and-files/
创建临时目录
NIO.2 提供了 createTempDirectory() 方法用于创建临时目录。这个方法会在系统默认临时目录位置创建临时目录。可以调用有两个参数的方法,第一个参数是临时目录命名前缀,可以为空,第二个可选参数是创建目录时设置的属性列表。下面的代码将创建两个临时目录,一个使用了前缀,另一个没有前缀:
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.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/
上一篇: 攻防世界PWN之cnss题解