38

Files.createTempDirectoryJVM正常退出后是否删除目录?还是我需要手动递归删除临时目录内容?

4

5 回答 5

57

系统退出时不会删除由创建的临时目录Files.createTempDirectory(),除非您将它们配置为这样做:

shutdown-hook或该机制File.deleteOnExit()可用于自动删除目录。

这意味着您可以致电:

Path tmp = Files.createTempDirectory(null);
tmp.toFile().deleteOnExit();

但是,除非目录为空,否则您不能删除目录,如文档File.delete()

删除此抽象路径名表示的文件或目录。如果此路径名表示一个目录,则该目录必须为空才能被删除。

因此,如果您希望删除目录及其内容,我们需要更花哨一些。您可以递归地注册一个目录及其子目录以进行删除,如下所示:

public static void recursiveDeleteOnExit(Path path) throws IOException {
  Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file,
        @SuppressWarnings("unused") BasicFileAttributes attrs) {
      file.toFile().deleteOnExit();
      return FileVisitResult.CONTINUE;
    }
    @Override
    public FileVisitResult preVisitDirectory(Path dir,
        @SuppressWarnings("unused") BasicFileAttributes attrs) {
      dir.toFile().deleteOnExit();
      return FileVisitResult.CONTINUE;
    }
  });
}

但是请注意,这会注册所有当前存在的文件以供删除 - 如果在调用此方法后创建新文件,它们及其父目录将不会根据File.delete().

如果要在退出时删除目录,无论所述目录的内容如何,​​都可以以几乎相同的方式使用关闭挂钩:

public static void recursiveDeleteOnShutdownHook(final Path path) {
  Runtime.getRuntime().addShutdownHook(new Thread(
    new Runnable() {
      @Override
      public void run() {
        try {
          Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file,
                @SuppressWarnings("unused") BasicFileAttributes attrs)
                throws IOException {
              Files.delete(file);
              return FileVisitResult.CONTINUE;
        }
        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException e)
            throws IOException {
          if (e == null) {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
          }
          // directory iteration failed
          throw e;
        }
        });
      } catch (IOException e) {
        throw new RuntimeException("Failed to delete "+path, e);
      }
    }}));
}

但是请注意,每次重复调用它都会注册一个新的关闭线程,这可能会导致大规模问题。 File.deleteOnExit()存储一组注册文件,并在一个关闭挂钩中删除所有文件。如果您需要以这种方式删除许多目录,则需要实现类似的东西。

于 2013-11-29T08:06:22.167 回答
29

根据API,不,不是,您需要使用file.deleteOnExit()方法手动删除目录。

与 createTempFile 方法一样,此方法只是临时文件工具的一部分。关闭挂钩或 File.deleteOnExit() 机制可用于自动删除目录。

于 2013-02-22T10:44:52.410 回答
23

您可以将 apache commons io 依赖项添加到您的项目中,然后使用 FileUtils.deleteDirectory() 执行以下操作:

Runtime.getRuntime().addShutdownHook(new Thread() {
    @Override
    public void run() {
        try {
            FileUtils.deleteDirectory(tmp_dir_path.toFile());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
});

有关 apache 公共检查的更多信息: https ://commons.apache.org/proper/commons-io/

于 2016-05-21T22:56:55.843 回答
2

不,它没有——createTempDirectory

createTempFile方法一样,此方法只是临时文件工具的一部分。shutdown-hook或该机制File.deleteOnExit() 可用于自动删除目录。

于 2013-02-22T10:47:58.950 回答
1

不,它没有。你必须自己做。或者使用java.io.File.deleteOnExit(),但我猜它不适用于非空目录

于 2013-02-22T10:42:00.057 回答