ZetCode

Java FileFilter 接口

最后修改时间:2025 年 4 月 16 日

java.io.FileFilter 接口用于过滤文件和目录。它包含一个方法,用于确定文件是否应包含在文件列表中。这通常与 File 类的 listFiles 方法一起使用。

FileFilter 是一个函数式接口,这意味着可以使用 lambda 表达式来实现它。它提供了一种灵活的方式来定制文件列表操作。该接口是 Java 1.2 以来 Java 文件 I/O 实用程序的一部分。

FileFilter 接口概述

FileFilter 接口只有一个抽象方法:accept。此方法接受一个 File 对象,并返回一个布尔值,指示是否应接受该文件。该接口通常与目录列表操作一起使用。

public interface FileFilter {
    boolean accept(File pathname);
}

上面的代码显示了 FileFilter 接口的简单结构。此接口的实现可以执行任何类型的文件过滤逻辑。在过滤操作期间,将为每个文件调用 accept 方法。

基本 FileFilter 实现

此示例演示了 FileFilter 接口的基本实现。我们将创建一个只接受具有特定扩展名的文件的过滤器。该实现使用匿名类来简化操作。

Main.java
import java.io.File;
import java.io.FileFilter;

public class Main {

    public static void main(String[] args) {
        File dir = new File(".");
        
        FileFilter txtFilter = new FileFilter() {
            @Override
            public boolean accept(File file) {
                return file.getName().endsWith(".txt");
            }
        };
        
        File[] txtFiles = dir.listFiles(txtFilter);
        
        System.out.println("Text files in current directory:");
        for (File file : txtFiles) {
            System.out.println(file.getName());
        }
    }
}

此示例创建一个只接受 .txt 文件的过滤器。listFiles 方法使用我们的过滤器返回匹配的文件。过滤器使用 endsWith 方法检查每个文件的名称。请注意,目录条目也会被检查,但不会匹配我们的标准。

Lambda 表达式实现

由于 FileFilter 是一个函数式接口,我们可以使用 lambda 表达式来实现它。这使得代码更简洁,同时保持相同的功能。Lambda 表达式是在 Java 8 中引入的。

Main.java
import java.io.File;

public class Main {

    public static void main(String[] args) {
        File dir = new File(".");
        
        // Using lambda expression
        File[] javaFiles = dir.listFiles(file -> file.getName().endsWith(".java"));
        
        System.out.println("Java files in current directory:");
        for (File file : javaFiles) {
            System.out.println(file.getName());
        }
    }
}

此示例展示了如何使用 lambda 表达式来实现 FileFilter。lambda 表达式接受一个 File 参数并返回一个布尔值。语法比匿名类实现更简洁。过滤器逻辑保持不变 - 检查文件扩展名。

组合多个条件

文件过滤器可以使用逻辑运算符组合多个条件。此示例演示了一个同时检查文件扩展名和文件大小的过滤器。我们将只接受大于 1KB 的 Java 文件。

Main.java
import java.io.File;
import java.io.FileFilter;

public class Main {

    public static void main(String[] args) {
        File dir = new File("src");
        
        FileFilter filter = file -> {
            boolean isJavaFile = file.getName().endsWith(".java");
            boolean isLargeEnough = file.length() > 1024;
            return isJavaFile && isLargeEnough;
        };
        
        File[] filteredFiles = dir.listFiles(filter);
        
        System.out.println("Large Java files in src directory:");
        for (File file : filteredFiles) {
            System.out.printf("%s (%,d bytes)%n", 
                file.getName(), file.length());
        }
    }
}

此示例在过滤器中组合了两个条件:文件扩展名和大小。length 方法返回文件大小(以字节为单位)。我们使用逻辑 AND (&&) 来要求两个条件都为真。输出显示文件名及其大小以进行验证。

仅限目录的过滤器

文件过滤器可以区分文件和目录。此示例创建一个只接受目录条目的过滤器。我们将使用 File 类的 isDirectory 方法。

Main.java
import java.io.File;

public class Main {

    public static void main(String[] args) {
        File rootDir = new File("/");
        
        File[] directories = rootDir.listFiles(File::isDirectory);
        
        System.out.println("Directories in root:");
        for (File dir : directories) {
            System.out.println(dir.getName());
        }
    }
}

此示例使用方法引用 (File::isDirectory) 作为实现过滤器的简洁方法。过滤器将只接受目录条目,排除常规文件。方法引用是 Java 8 的另一个功能,它简化了函数式接口的实现。

自定义过滤器类

对于复杂的过滤逻辑,我们可以创建专用的过滤器类。此示例展示了一个自定义过滤器,该过滤器接受在过去 7 天内修改的文件。该类显式实现 FileFilter

Main.java
import java.io.File;
import java.io.FileFilter;
import java.util.Date;

public class Main {
    
    static class RecentFileFilter implements FileFilter {
        private long cutoffTime;
        
        public RecentFileFilter(int days) {
            long millisPerDay = 24 * 60 * 60 * 1000L;
            this.cutoffTime = System.currentTimeMillis() - (days * millisPerDay);
        }
        
        @Override
        public boolean accept(File file) {
            return file.lastModified() >= cutoffTime;
        }
    }

    public static void main(String[] args) {
        File dir = new File(".");
        
        FileFilter filter = new RecentFileFilter(7);
        File[] recentFiles = dir.listFiles(filter);
        
        System.out.println("Files modified in last 7 days:");
        for (File file : recentFiles) {
            System.out.printf("%s - %s%n", 
                file.getName(), new Date(file.lastModified()));
        }
    }
}

此示例演示了更复杂的过滤器实现。RecentFileFilter 类维护状态(截止时间)并实现复杂的逻辑。过滤器根据我们的截止时间检查每个文件的上次修改时间戳。输出显示文件名及其修改日期。

组合多个过滤器

我们可以组合多个过滤器来创建更具体的选择标准。此示例展示了如何依次应用两个过滤器以获取符合两个条件的文件。我们将找到同时是 PDF 文件且可读的文件。

Main.java
import java.io.File;
import java.io.FileFilter;

public class Main {

    public static void main(String[] args) {
        File dir = new File("documents");
        
        FileFilter pdfFilter = f -> f.getName().toLowerCase().endsWith(".pdf");
        FileFilter readableFilter = File::canRead;
        
        File[] files = dir.listFiles(f -> 
            pdfFilter.accept(f) && readableFilter.accept(f));
        
        System.out.println("Readable PDF files:");
        for (File file : files) {
            System.out.println(file.getName());
        }
    }
}

此示例在 lambda 表达式中使用逻辑 AND 组合了两个过滤器。首先,我们检查该文件是否为 PDF,然后检查它是否可读。canRead 方法检查文件权限。组合的过滤器只接受满足这两个条件的文件。

来源

Java FileFilter 接口文档

在本文中,我们介绍了 Java FileFilter 接口的基本方法和特性。了解这些概念对于在 Java 应用程序中使用文件操作至关重要。

作者

我叫 Jan Bodnar,是一名经验丰富的程序员。我于 2007 年开始撰写编程文章,至今已撰写了超过 1,400 篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程