【问题标题】:Array of Path using nio使用 nio 的路径数组
【发布时间】:2020-09-22 15:34:33
【问题描述】:

我只是在研究主题 nio 并得到了以下任务: 使用 nio 对文件名进行递归搜索。该方法应返回找到的路径列表。 当我在输出中运行下面的代码时,我只看到 [ ]。有人可以解释并纠正我吗?

public class Task01 {
    public static void main(String[] args) throws IOException {
        Path dir = Paths.get("C:\\Users\\......");
        System.out.println(findFile(dir, "Task01.java"));
    }

    public static ArrayList<Path> findFile(Path path, String filename) throws IOException {
        Path dir = Paths.get("C:\\....");
        ArrayList<Path> list1 = new ArrayList<>();

        try (DirectoryStream<Path> stream = Files.newDirectoryStream(path, filename)) {
            for (Path entry : stream) {
                if (path.toFile().isDirectory()) {
                    findFile(path, filename);
                } else list1.add(entry.toAbsolutePath());
            }

        }
        return list1;
    }
}

【问题讨论】:

  • 在您的if..else 语句中,使用entry 而不是path

标签: java nio


【解决方案1】:

此代码可能对您有用:

public static ArrayList<Path> findFile(Path path, String filename) throws IOException {
    ArrayList<Path> list1 = new ArrayList<>();

    try (DirectoryStream<Path> stream = Files.newDirectoryStream(path,filename)) {
        for (Path entry : stream) {
            System.out.println(entry+ "-"+entry.getFileName());
            if (Files.isDirectory(entry)) {
                list1.addAll(findFile(entry, filename));
            } 
            else if (entry.getFileName().toString().equals(filename)) 
                list1.add(entry.toAbsolutePath());
        }

    }
    return list1;
}
  • 将文件名传递给 Files.newDirectoryStream(path,filename) 时,它只会在路径本身中搜索,不搜索子目录。所以你可能不会在这里传递文件名来过滤。
  • 如果您递归调用您的方法,您还必须确保返回值向上传递:list1.addAll(findFile(entry, filename));
  • 在 for 循环中始终使用 entry,而不是 path,否则您不会递归处理您的目录结构。 (见Files.isDirectory(entry) 而不是path.toFile().isDirectory()

更新:改进了 java.nio API 的使用(感谢@Andreas)。没错,我对nio api 不太熟悉。

【讨论】:

  • 赞成,但是:除非绝对必要,否则不要混合新旧 API,所以不要调用 toFile()! --- 不要使用entry.toFile().isDirectory(),使用Files.isDirectory(entry)。 --- 不要使用entry.toFile().getName(),使用entry.getFileName().toString()。更好的是,使用else if (entry.endsWith(filename)) 。 --- 另外,entry.getName(entry.getNameCount()-1) 是一种非常冗长的写法entry.getFileName()
【解决方案2】:

首先,在做递归的时候,你要使用entry而不是path,否则你不会顺着目录树下去。

也使用Files.newDirectoryStream(path) 而不是Files.newDirectoryStream(path, fileNamePattern) 第二种方法在文件名与fileNamePattern 匹配的路径中创建一个流,在您的情况下,如果您的Test.java 不在path 中,它将为空[] /p>

public static void main(String[] args) throws IOException {
    Path dir = Paths.get("E:\\dev\\...");
    System.out.println(findFile(dir, "TestA.java"));
}

public static ArrayList<Path> findFile(Path path, String filename) throws IOException {
    ArrayList<Path> list1 = new ArrayList<>();

    try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
        for (Path entry : stream) {
            if (Files.isDirectory(entry)) {
               list1.addAll(findFile(entry, filename));
            } else if(entry.getFileName().endsWith(filename)){
               list1.add(entry.toAbsolutePath());
            }
        }
    }
    return list1;
}

【讨论】:

  • 使用Files.isDirectory(entry)。 --- 为什么在endsWith() 之前调用getName()?这是不必要的。此外,getFileName()getName(entry.getNameCount()-1) 更短/更准确,如果您必须执行该操作的话。
  • @Andreas 正确,我根据您的 cmets 对代码进行了修改
  • 不,你没有,你在尝试应用第二部分时弄乱了代码,而你没有做第一部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
相关资源
最近更新 更多