在JVM正常退出后,Files.createTempDirectory是否删除目录?

28 java

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

dim*_*414 45

Files.createTempDirectory()系统退出时,不会删除创建的临时目录,除非您将它们配置为执行此操作:

可以使用shutdown-hookFile.deleteOnExit()机制自动删除目录.

意思是你可以打电话:

Path tmp = Files.createTempDirectory(null);
tmp.toFile().deleteOnExit();
Run Code Online (Sandbox Code Playgroud)

但是,您不能删除目录,除非它是空的,因为文档由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;
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

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

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

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);
      }
    }}));
}
Run Code Online (Sandbox Code Playgroud)

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

  • 在Spring中有一个辅助方法`org.springframework.util.FileSystemUtils.deleteRecursively(File root)`用于显式递归目录删除. (6认同)

Pra*_*mha 22

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

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

  • @PradeepSimha - 是什么让你说你不能通过 `null`?你当然可以调用 [`Files.createTempDirectory(null)`](http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#createTempDirectory(java.lang.String ,%20java.nio.file.attribute.FileAttribute...)),这完全符合人们的预期——它创建一个新的任意命名的目录并返回其路径。 (4认同)
  • @HowardGuo,我不这么认为,你将null传递给createTempDirectory方法 (2认同)
  • @HowardGuo,http://docs.oracle.com/javase/tutorial/essential/io/dirs.html 这应该给你更多信息 (2认同)

Yah*_*hya 16

您可以将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();
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

有关apache commons的更多信息,请访问:https: //commons.apache.org/proper/commons-io/

  • 值得注意的是,这会删除目录,无论它是否为空. (2认同)