在Java中使用Files/Folders


Java NIO.2 API提供了对使用临时文件夹/文件的支持。例如,我们可以轻松地找到临时文件夹/文件的默认位置,如下所示:

String defaultBaseDir = System.getProperty("java.io.tmpdir");

通常,在Windows中,默认的临时文件夹为 C:\Temp%Windows%\Temp或每个用户所在的临时目录 Local Settings\Temp(此位置通常由TEMP 环境变量控制 )。

Linux / Unix中,全局临时目录是 /tmp 和 /var/tmp 。前一行代码将返回默认位置,具体取决于操作系统。接下来,我们将学习如何创建一个临时文件夹/文件。

您可能还会喜欢: 在日期和时间之间进行转换的实用指南 创建一个临时文件夹/文件 创建临时文件夹可以使用以下方法完成:

Path createTempDirectory (Path dir, String prefix, FileAttribute<?>... attrs) 这是该类中的一种 static方法 Files ,可以按如下方式使用:

让我们在操作系统的默认位置创建一个没有前缀的临时文件夹:

// C:\Users\Anghel\AppData\Local\Temp\8083202661590940905
Path tmpNoPrefix = Files.createTempDirectory(null);

让我们在操作系统的默认位置创建一个带有自定义前缀的临时文件夹:

// C:\Users\Anghel\AppData\Local\Temp\logs_5825861687219258744
String customDirPrefix = "logs_";
Path tmpCustomPrefix = Files.createTempDirectory(customDirPrefix);

让我们在带有自定义前缀的自定义位置中创建一个临时文件夹:

// D:\tmp\logs_10153083118282372419
Path customBaseDir = FileSystems.getDefault().getPath("D:/tmp");
String customDirPrefix = "logs_";
Path tmpCustomLocationAndPrefix = Files.createTempDirectory(customBaseDir, customDirPrefix);

创建临时文件可以通过以下方式完成:

Path createTempFile (Path dir, String prefix, String suffix, FileAttribute<?>... attrs 这是该类中的一种static方法Files ,可以按如下方式使用:

让我们在操作系统的默认位置创建一个没有前缀和后缀的临时文件:

// C:\Users\Anghel\AppData\Local\Temp\16106384687161465188.tmp
Path tmpNoPrefixSuffix = Files.createTempFile(null, null);

让我们在操作系统的默认位置创建一个带有自定义前缀和后缀的临时文件:

// C:\Users\Anghel\AppData\Local\Temp\log_402507375350226.txt
String customFilePrefix = "log_";
String customFileSuffix = ".txt";
Path tmpCustomPrefixAndSuffix = Files.createTempFile(customFilePrefix, customFileSuffix);

让我们在带有自定义前缀和后缀的自定义位置中创建一个临时文件:

// D:\tmp\log_13299365648984256372.txt
Path customBaseDir = FileSystems.getDefault().getPath("D:/tmp");
String customFilePrefix = "log_";
String customFileSuffix = ".txt";
Path tmpCustomLocationPrefixSuffix 
    = Files.createTempFile(customBaseDir, customFilePrefix, customFileSuffix);

接下来,我们将研究删除临时文件夹/文件的不同方法。

通过关机挂钩删除临时文件夹/文件 删除临时文件夹/文件是可以由操作系统或专用工具完成的任务。但是,有时,我们需要以编程方式进行控制,并根据不同的设计考虑来删除文件夹/文件。

该问题的解决方案依赖于可通过该方法实现的关机挂钩机制 Runtime.getRuntime().addShutdownHook() 。每当我们需要在JVM关闭之前立即完成某些任务(例如,清理任务)时,此机制就很有用。它作为Java线程实现,run() 当JVM在关闭时执行shutdown-hook时,将调用该 方法的方法。如下代码所示:

Path customBaseDir = FileSystems.getDefault().getPath("D:/tmp");
String customDirPrefix = "logs_";
String customFilePrefix = "log_";
String customFileSuffix = ".txt";

try {
  Path tmpDir = Files.createTempDirectory(customBaseDir, customDirPrefix);
  Path tmpFile1 = Files.createTempFile(tmpDir, customFilePrefix, customFileSuffix);
  Path tmpFile2 = Files.createTempFile(tmpDir, customFilePrefix, customFileSuffix);


  Runtime.getRuntime().addShutdownHook(new Thread() {


    @Override
    public void run() {
      try (DirectoryStream<Path> ds = Files.newDirectoryStream(tmpDir)) {
        for (Path file: ds) {
          Files.delete(file);
        }

        Files.delete(tmpDir);
      } catch (IOException e) {

        ...
      }
    }
  });

  //simulate some operations with temp file until delete it
  Thread.sleep(10000);
} catch (IOException | InterruptedException e) {
  ...
}

甲关闭钩不会在异常/强制终止的情况下被执行(例如,JVM崩溃,触发终端的操作,等等)。它在所有线程完成或被 System.exit(0) 调用时运行。建议快速运行它,因为如果出现问题(例如,操作系统关闭),可以在完成之前将它们强行停止。以编程方式,shutdown-hook只能通过停止 Runtime.halt() 。

通过deleteOnExit()删除临时文件夹/文件 删除临时文件夹/文件的另一种解决方案依赖于该 File.deleteOnExit()方法。通过调用此方法,我们可以注册删除文件夹/文件。删除操作在JVM关闭时发生:

Path customBaseDir = FileSystems.getDefault().getPath("D:/tmp");
String customDirPrefix = "logs_";
String customFilePrefix = "log_";
String customFileSuffix = ".txt";

try {
  Path tmpDir = Files.createTempDirectory(customBaseDir, customDirPrefix);
  System.out.println("Created temp folder as: " + tmpDir);
  Path tmpFile1 = Files.createTempFile(tmpDir, customFilePrefix, customFileSuffix);
  Path tmpFile2 = Files.createTempFile(tmpDir, customFilePrefix, customFileSuffix);

  try (DirectoryStream<Path> ds = Files.newDirectoryStream(tmpDir)) {
    tmpDir.toFile().deleteOnExit();


    for (Path file: ds) {      
      file.toFile().deleteOnExit();
    }
  } catch (IOException e) {
    ...
  }

  // simulate some operations with temp file until delete it
  Thread.sleep(10000);
} catch (IOException | InterruptedException e) {
  ...
}

建议仅deleteOnExit()在应用程序管理少量临时文件夹/文件时才依靠此方法()。此方法可能会消耗大量内存(它为注册为删除的每个临时资源消耗内存),并且直到JVM终止,才可能释放该内存。

请注意,由于需要调用此方法来注册每个临时资源,并且删除是以相反的注册顺序进行的(例如,在注册其内容之前,我们必须先注册一个临时文件夹)。

通过DELETE_ON_CLOSE删除临时文件 删除临时文件所依赖的另一种解决方案 StandardOpenOption.DELETE_ON_CLOSE (在关闭流时删除该文件)。例如,下面的代码段通过createTempFile() 方法创建一个临时文件,并为该文件打开一个DELETE_ON_CLOSE 显式指定的缓冲写流:

Path customBaseDir = FileSystems.getDefault().getPath("D:/tmp");
String customFilePrefix = "log_";
String customFileSuffix = ".txt";
Path tmpFile = null;

try {
  tmpFile = Files.createTempFile(
    customBaseDir, customFilePrefix, customFileSuffix);
} catch (IOException e) {
  ...
}


try (BufferedWriter bw = Files.newBufferedWriter(tmpFile,
       StandardCharsets.UTF_8, StandardOpenOption.DELETE_ON_CLOSE)) {


  //simulate some operations with temp file until delete it
  Thread.sleep(10000);
} catch (IOException | InterruptedException e) {
  ...
}

该解决方案可用于任何文件。它不特定于临时资源。

完整的示例可在 GitHub上 使用前缀P142_ foo获得。

如果您喜欢本文,那么您会喜欢我的书 Java Coding Problems,其中有专门的章节,其中包括20个专门针对Java I / O的问题。

祝您编码愉快!


原文链接:https://codingdict.com/