[Java 8] 列举目录下的所有文件和监视文件变化

列举目录中的所有文件

首先给出代码:

Files.list(Paths.get(".")).forEach(System.out::println);

Files.list方法得到的是一个Stream类型的对象,它代表了目标路径下所有的文件。如果只想获取目标路径下的所有目录文件:

Files.list(Paths.get("."))
    .filter(Files::isDirectory)
    .forEach(System.out::println);

在以前的Java版本中,如果需要实现一个自定义的过滤器,那么通常会选择使用FilenameFilter结合匿名类的方式:

final String[] files =
    new File("target_dir").list(new java.io.FilenameFilter() {
    public boolean accept(final File dir, final String name) {
        return name.endsWith(".java");
    }
});
System.out.println(files);

我们说过,当遇见了匿名内部类的时候,如果被实现的接口是一个函数式接口,那么可以考虑将该匿名内部类以Lambda表达式的形式重新实现,再结合Java 8中新添加的DirectoryStream,可以将上述代码重新实现为:

Files.newDirectoryStream(
    Paths.get("target_dir"),
    path -> path.toString().endsWith(".java"))
        .forEach(System.out::println);

当目标目录下含有大量的文件或者子目录时,使用DirectoryStream往往会具有更好的性能。因为它实际上是一个Iterator用来遍历目标目录,而直接使用listFiles方法时,得到的是一个代表了所有文件和目录的数组,意味着内存的开销会更大。

使用flatMap列举所有直接子目录

所谓的直接子目录(Immediate Subdirectory),指的就是目标目录下一级的所有目录。对于这样一个任务,最直观的实现方式恐怕是这样的:

public static void listTheHardWay() {
    List<File> files = new ArrayList<>();
    File[] filesInCurerentDir = new File(".").listFiles();
    for(File file : filesInCurerentDir) {
        File[] filesInSubDir = file.listFiles();
        if(filesInSubDir != null) {
            files.addAll(Arrays.asList(filesInSubDir));
        } else {
            files.add(file);
        }
    }
    System.out.println("Count: " + files.size());
}

很显然,此段代码噪声太多,没有清晰地反映出代码的整体目标。下面就用flatMap方法来简化它:

public static void betterWay() {
    List<File> files = Stream.of(new File(".").listFiles())
        .flatMap(file -> file.listFiles() == null ?
            Stream.of(file) : Stream.of(file.listFiles()))
        .collect(toList());
    System.out.println("Count: " + files.size());
}

// flatMap
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

从flatMap方法的签名来看,它接受了一个Function接口作为参数,将一种类型转换为另一种类型的Stream类型。而从flatMap方法的命令来看,它的执行过程主要包含两个步骤:

  1. 首先是会对当前Stream的每个元素执行一次map操作,根据传入的mapper对象将一个元素转换为对应的Stream对象
  2. 将第一步中得到的若干个Stream对象汇集成一个Stream对象

从上面的代码来看,签名中的T类型就是File类型,而R类型同样也是File类型。当一个File对象不含有任何的子目录或者子文件时,那么通过Stream.of(file)来仅仅包含它自身,否则使用Stream.of(file.listFiles())来包含其下的所有子目录和子文件。

监视文件变化

WatchService是Java 7中新添加的一个特性,用来监视一某个路径下的文件或者目录是否发生了变化。

final Path path = Paths.get(".");
final WatchService watchService = path.getFileSystem().newWatchService();

path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

System.out.println("Report any file changed within next 1 minutes...");

注册了需要监视的目录后,需要使用WatchKey来得到一段时间内的,该目录的变化情况:

final WatchKey watchKey = watchService.poll(1, TimeUnit.MINUTES);
if(watchKey != null) {
    watchKey.pollEvents().stream().forEach(event ->
    System.out.println(event.context()));
}

这里使用了Java 8中的内部遍历器forEach来完成对于事件的遍历。这也算是一个Java 7和Java 8特性的联合使用吧。

时间: 2024-11-05 19:05:05

[Java 8] 列举目录下的所有文件和监视文件变化的相关文章

Java版本的删除指定目录下名叫“xxx.txt”文件名的文件

以前写过一个python版本的,但是在查找文件路径的时候出现错误,无法正确的获取到文件的路径,就造成无法删除该路径下的“xxx.txt”文件. 当时以为是windows版本系统的错误造成这个问题的,也就没有继续深究,就把这个bug给放过了. 最近一段时间在学习android,肯定要用的java了,就用java实现了下,思路的话,肯定还是以前的了,结果还是出错,后来仔细的看了看代码,其实是自己的bug. 把代码贴下:(主要功能,删除指定目录下名叫"pylist.txt"的所有文件,使用递

Java实现列出目录下所有文件和文件夹

1 package com.filetest; 2 3 import java.io.File; 4 import java.util.Scanner; 5 6 public class fileview { 7 8 public static void main(String args[]){ 9 10 view(); //调用查看文件列表函数 11 12 } 13 14 private static void view() { 15 16 Scanner scanner=new Scanne

计算目录下的md5值,用于文件被篡改后对比

计算/etc目录下的md5值,用于文件被篡改后对比,命令如下: find /etc/ -maxdepth 1 -type f | xargs -n1 md5sum> /root/etc_sum-$(date +%F).log 同样的道理, 我们可以将/usr/bin  /usr/sbin/ /usr/local/bin /root/bin 等等重要的目录下面的文件校验和都计算一遍,这样的话定期执行一下该命令,生成一份最新的校验和,通过diff命令将生成的log文件和原始的md5sum.log比较

查找目录下匹配.py或者.txt的文件

#!/usr/bin/python def endWith(s,*endstring_1):       #*代表允许传输多个参数,名称统一为endstring为元祖,**为字典 array = map(s.endswith,endstring_1)  #map(调用的函数名称,给这个函数传的参数) if True in array: return True else: return False if __name__ == '__main__': import os s = os.listdi

Java使用递归找出某目录下的所有子目录以及子文件

1 /* 2 使用递归找出某目录("C:\\JavaProducts")下的所有子目录以及子文件 3 */ 4 5 import java.util.*; 6 import java.io.*; 7 8 public class FileRecursionPrintDemo{ 9 public static void main(String[] args){ 10 List<String> paths = new ArrayList<String>(); 11

java 读取固定目录下的文件(和上篇差点儿相同)

package gao.org; import java.io.FileNotFoundException; import java.io.IOException; import java.io.File; public class ReadFile { public ReadFile() { } /** * 读取某个目录下的全部文件 */ public static boolean readfile(String filepath) throws FileNotFoundException,

Java读取指定目录下的所有文件(子目录里的文件也可递归得到)

1 import java.io.File; 2 3 public class ReadFile { 4 5 public static void main(String[] args) { 6 7 // path是指定目录的绝对路径 8 String path = "/Users/tonychan/Workspaces/MyEclipse 2017 CI/Zhangjiajie/WebRoot/pics"; 9 getFile(path); 10 11 } 12 13 // 给定目录

JAVA输出指定目录下的子目录和子文件

题目:给定一个目录,要求输出这个目录下面的子目录和子文件 逻辑: 先判断给定的是不是一个合法的目录,如果不是,则提示给定错误 如果是目录,那么使用File.listFile()获得这个目录下文件名的数组 循环遍历输出这个数组元素 输出名称之后,接着判断这个元素是文件还是目录 如果是目录,继续调用本方法来输出子目录 代码如下: /** * 输出指定目录下的所有子目录和子文件 * * @author DXY * */ public class HelloFile { public static vo

java读取某个目录下所有文件并通过el表达式将相关文件信息展示出来,js提供页面搜索及查看下载功能

从服务器上读取某个目录下的文件  将文件名 文件修改日期   及文件 大小展示在前台  并可以查看及下载 第一步:读取文件目录下的文件,并将文件按时间由大到小排列 public ArrayList<File> getLogs() { // TODO Auto-generated method stub ArrayList<File>  tomcatLogs = new ArrayList<File>(); File path = new File(""