java - "try-with-resources"在删除给定目录节点下的所有文件和文件夹的程序上下文中如何实际工作

标签 java try-with-resources directorystream

此程序删除给定节点下的所有文件和文件夹。

*编辑*

我在驱动器 K 上有以下“测试”目录结构:

Folder K:\garbage\
f_00000b (file)
f_00000f ( " )
f_0000b3 ( " )
dir1    [FOLDER]

Folder K:\garbage\dir1\
abc.pdf (file)
b12.pdf (file)
b36.pdf (file)
dir2   [FOLDER]

Folder K:\garbage\dir1\dir2\
A.pdf   (file)
a1.pdf  (file)
A2.pdf  (file)

*结束编辑*

程序之所以有效,是因为我偶然发现了“try-with-resources”,所有////////////////////////包围的行都是“资源”。

import java.io.IOError;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import javax.swing.JOptionPane;

public class CreatingDirectories {

    public static void main(String[] args) {

      deleteEverythingBelowThisNode(Paths.get("K:/garbage/dir1/dir2"));
    }

    static void deleteAllFilesIn(String ps){

      Path p = Paths.get(ps);

      try ////////////////////////////////////////////////////////////////
         (DirectoryStream<Path> paths = Files.newDirectoryStream(p)) /////
      { //////////////////////////////////////////////////////////////////

        for(Path q: paths)
          Files.delete(q);

      }catch(NotDirectoryException e){
        System.out.println("Not directory: " + p.toString() + "--" + e);
      }catch(DirectoryNotEmptyException e){
        System.out.println("Not empty: " + p.toString() + "--" + e);
      }
      catch(IOException e){
        System.out.println("IO: " + p.toString() + "--" + e);
      }
      catch(IOError e){
        System.out.println("IO ERROR: " + e);
      }
    }

    static void deleteEverythingBelowThisNode(Path p){

      String            sep        = p.getFileSystem().getSeparator();
      ArrayList<String> pathPieces = new ArrayList<>() ;
      String []         paths      = new String[p.getNameCount()];

      for(int i = 0 ; i < p.getNameCount() ; i++){
        pathPieces.add(p.getName(i).toString());
        paths[i] = p.getRoot().toString();
      }

      for(int i = 0; i < p.getNameCount() ; i++)
        for(int k = 0; k <= i; k++)
          paths[i] += pathPieces.get(k) + sep;

      for(int k = p.getNameCount() - 1; k >= 0; k--)
        deleteAllFilesIn(paths[k]);
    }
}

我知道“try-with-resources”是必要的:程序可以使用它,而不是没有它。

但我不明白为什么,也不知道它是如何解决我现在描述的原始问题的。

我最初将“资源”置于 try block 之上,就像这样,这看起来非常自然:

      DirectoryStream<Path> paths = Files.newDirectoryStream(p);
      try {
           for...

除了如上所示移动那一行之外,程序结构在其他方面完全相同,所有文件和子文件夹已成功从文件夹中删除,但抛出 DirectoryNotEmptyException。程序因异常终止后,Windows Explorer 确认该目录为空。

为什么在空目录上抛出异常?

来自 the horse's mouth , "try-with-resources 语句...声明...一个对象...在语句末尾关闭。"

关闭发生在语句的末尾,所以在循环的末尾。怎么用try-with-resources也没有出现异常?

就像现在一样,循环遍历整个节点后,它下面的所有内容都已删除。

那么 try-with-resources 实际上做了什么来启用删除没有 try-with-resources 无法删除的空文件夹?

这些看起来不像是愚蠢的问题或微不足道的情况。

DirectoryNotEmptyException 是否确实发生了,但 try-with-resources 以某种方式处理了它?我不敢相信我会问这个问题,因为这看起来确实是一个愚蠢的问题,但是究竟发生了什么让程序按预期运行?

最佳答案

在 Windows 上,您无法删除仍处于打开状态的文件或目录。 (另一方面,在 Unix 上,这不是问题 - 当您删除文件时,文件将从目录结构中删除,当您关闭它时,文件将从磁盘中删除。但那是在 Unix 上。)

因此,如果您不使用 try-with-resources 语句关闭目录流,那么在您尝试删除父目录中的文件的那一刻,您仍然会打开子目录,并且尝试删除子目录仍然打开的将失败。由于您忽略异常(您只是打印它们),随后删除父目录的尝试也将失败并返回 DirectoryNotEmptyException,因为您没有删除所有子目录。

您可以验证是否确实如此。当您使用 try-with-resources 时,请确保在删除目录中的所有文件后明确关闭目录流(使用 paths.close(); )

这应该与 try-with-resources block 具有相同的效果(除非发生异常 - 为了保证与 try-with-resources 完全相同的行为,您需要放置 paths.close();finally block 中)。

关于java - "try-with-resources"在删除给定目录节点下的所有文件和文件夹的程序上下文中如何实际工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22056960/

相关文章:

java - 列出目录中与文件掩码(又名模式或 Glob)匹配的所有文件

java - Quarkus + Kafka + Smallrye 异常处理

java - Spring Security数据库实现异常

java - AutoCloseable.close()方法是否违反了Java的向后兼容性规则

java - 错误的资源泄漏警告?

java - 如何根据 "last modified"计算每小时的文档数

java - DirectoryStream返回路径以什么样的顺序?文件名、最后修改时间、文件大小?

java - 如何查看当前线程堆和变量?

java - Android USB 连接状态;

java - SQL 连接悬空 : Where am I not correctly closing up connections correctly?