用Java实现文件搜索

Hello World, Hello Java Files

Posted by Resulte on March 5, 2020

文件搜索

文件搜索是操作系统中非常常见的应用,需要从指定目录下寻找到目标文件。

下面我以在C:\target目录下,寻找所有Java文件为例,简单总结了几个实现方法。

注:寻找所有Java文件,也就是寻找所有文件名以.java结尾的文件

1. 递归遍历搜索

分析:

  • 目录搜索,无法判断多少级目录,所以使用递归,遍历所有目录。
  • 遍历目录时,获取的子文件,通过文件名称,判断是否符合条件。
public class FileTest {
    public static void main(String[] args) throws IOException {
        // 创建File对象
        File dir = new File("`C:\\target`");
        //递归搜索
        findALLFiles(dir); 
    }
    private static void findALLFiles(File dir) {
        // 获取当前目录下的所有子文件和目录
        File[] files = dir.listFiles();
        for (File file : files) { 
            if (file.isFile()) { 
                // 是文件,判断文件名并输出文件名 
                if (file.getName().endsWith(".java")) { 
                    System.out.println("find target file:" + file.getName()); 
                } 
            } else { 
                // 是目录,继续遍历,形成递归 
                findALLFiles(file); 
            } 
        }
    }
}

注:因为文件路径不区分大小写,故判断文件名时可以先将文件名转成小写字母,再进行判断,即file.getName().toLowerCase().endsWith(".java")

2. 使用文件过滤器

使用java.io.FileFilter接口,这是File的过滤器。 该接口的对象可以传递给File类的 listFiles(FileFilter) 作为参数,起到过滤文件的作用。

但是需要重写该接口的boolean accept(File pathname) 方法,该方法测试pathname是否应该包含在当前File目录中,符合则返回true

分析:

  • 使用FileFilter接口作为参数,需要传递子类对象,重写其中方法。我们可以选择匿名内部类方式。
  • 重写 accept 方法,参数为File类型,表示当前File下所有的子文件和子目录。保留住则返回true,过滤掉则返回 false。保留规则:
    1. 如果是文件,则保留.java文件
    2. 如果是目录,则都保留,用于递归遍历
  • 通过过滤器的作用, listFiles(FileFilter) 返回的数组元素中,子文件对象都是符合条件的,可以直接输出。
public class FileTest {
    public static void main(String[] args) throws IOException {
        // 创建File对象
        File dir = new File("`C:\\target`");
        //递归搜索
        findALLFiles(dir); 
    }
    private static void findALLFiles(File dir) {
        // 匿名内部类方式,创建过滤器子类对象
        File[] files = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(".java");
            }
        });
        for (File file : files) { 
            if (file.isFile()) { 
                // 是文件,则由于过滤过,则一定是目标文件 
                System.out.println("find target file:" + file.getName()); 
            } else { 
                // 是目录,继续遍历,形成递归 
                findALLFiles(file); 
            } 
        }
    }
}

当然,我们也可以非常优雅的使用Lambda表达式简化一下~

public class FileTest {
    public static void main(String[] args) throws IOException {
        // 创建File对象
        File dir = new File("`C:\\target`");
        //递归搜索
        findALLFiles(dir); 
    }
    private static void findALLFiles(File dir) {
        // Lambda方式,创建过滤器子类对象
        File[] files = dir.listFiles((pathname) -> {
            return pathname.isDirectory() || pathname.getName().toLowerCase().endsWith(".java");
        });
        for (File file : files) { 
            if (file.isFile()) { 
                // 是文件,则由于过滤过,则一定是目标文件 
                System.out.println("find target file:" + file.getName()); 
            } else { 
                // 是目录,继续遍历,形成递归 
                findALLFiles(file); 
            } 
        }
    }
}