ZetCode

Java FilenameFilter 接口

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

java.io.FilenameFilter 接口用于过滤目录列表中的文件名。它包含一个方法,用于测试指定的文件是否应包含在文件列表中。当您需要处理目录中的特定类型的文件时,这特别有用。

FilenameFilter 是一个函数式接口,这意味着可以使用 lambda 表达式来实现它。它通常与 File 类的 list 方法一起使用,以获取经过过滤的目录内容。该接口提供了一种自定义文件列表行为的简单方法。

FilenameFilter 接口概述

FilenameFilter 接口只有一个方法需要实现。此方法确定是否应接受或过滤掉文件。该接口是 Java I/O 包的一部分,自 JDK 1.0 起可用。

public interface FilenameFilter {
    boolean accept(File dir, String name);
}

accept 方法接受两个参数:包含文件的目录和文件名。如果文件应包含在列表中,则返回 true。在使用 File.list 时,将为目录中的每个文件调用该方法。

基本的 FilenameFilter 实现

此示例展示了如何实现 FilenameFilter 接口来过滤文本文件。我们创建一个实现该接口的类,并重写 accept 方法。该过滤器检查 .txt 扩展名。

Main.java
import java.io.File;
import java.io.FilenameFilter;

public class Main {
    
    static class TextFileFilter implements FilenameFilter {
        @Override
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".txt");
        }
    }

    public static void main(String[] args) {
        File directory = new File(".");
        
        // Get all text files in current directory
        String[] textFiles = directory.list(new TextFileFilter());
        
        if (textFiles != null) {
            System.out.println("Text files in current directory:");
            for (String file : textFiles) {
                System.out.println(file);
            }
        }
    }
}

此示例演示了 FilenameFilter 的基本实现。TextFileFilter 类检查文件名是否以 “.txt” 结尾。list 方法使用此过滤器仅返回匹配的文件。请注意,我们检查 null,以防目录不存在或不可读。

将 Lambda 表达式与 FilenameFilter 一起使用

由于 FilenameFilter 是一个函数式接口,我们可以使用 lambda 表达式来实现简洁的实现。这种方法减少了样板代码,并使过滤逻辑在实现简单时更具可读性。

Main.java
import java.io.File;

public class Main {
    public static void main(String[] args) {
        File directory = new File(".");
        
        // Filter for Java source files using lambda
        String[] javaFiles = directory.list((dir, name) -> 
            name.toLowerCase().endsWith(".java"));
        
        if (javaFiles != null) {
            System.out.println("Java source files:");
            for (String file : javaFiles) {
                System.out.println(file);
            }
        }
    }
}

此示例展示了如何使用 lambda 表达式而不是单独的类来实现 FilenameFilter。lambda 表达式检查 .java 文件。语法更紧凑,同时保持与基于类的方法相同的功能。这对于一次性过滤器特别有用。

按前缀过滤文件

我们可以通过组合多个条件来实现更复杂的过滤逻辑。此示例过滤以特定前缀开头且具有特定扩展名的文件。accept 方法可以包含所需的任何自定义逻辑。

Main.java
import java.io.File;
import java.io.FilenameFilter;

public class Main {
    
    static class PrefixFilter implements FilenameFilter {
        private final String prefix;
        
        public PrefixFilter(String prefix) {
            this.prefix = prefix;
        }
        
        @Override
        public boolean accept(File dir, String name) {
            return name.startsWith(prefix) && 
                   name.toLowerCase().endsWith(".log");
        }
    }

    public static void main(String[] args) {
        File directory = new File("/var/log");
        
        // Filter for system log files starting with 'syslog'
        String[] systemLogs = directory.list(new PrefixFilter("syslog"));
        
        if (systemLogs != null) {
            System.out.println("System log files:");
            for (String file : systemLogs) {
                System.out.println(file);
            }
        }
    }
}

此示例演示了更复杂的过滤器,该过滤器同时检查前缀和扩展名。PrefixFilter 类将前缀作为构造函数参数,使其可重用。accept 方法使用逻辑 AND 组合这两个条件。此模式允许灵活创建过滤器。

不区分大小写的文件过滤

文件系统通常具有区分大小写的名称,但我们可能需要不区分大小写的过滤。此示例展示了如何为文件扩展名实现不区分大小写的过滤。我们将文件名和模式都转换为相同的大小写。

Main.java
import java.io.File;
import java.io.FilenameFilter;

public class Main {
    
    static class CaseInsensitiveFilter implements FilenameFilter {
        private final String extension;
        
        public CaseInsensitiveFilter(String ext) {
            this.extension = ext.startsWith(".") ? ext : "." + ext;
        }
        
        @Override
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(extension.toLowerCase());
        }
    }

    public static void main(String[] args) {
        File directory = new File(".");
        
        // Filter for image files (case insensitive)
        String[] images = directory.list(new CaseInsensitiveFilter("JPG"));
        
        if (images != null) {
            System.out.println("Image files:");
            for (String file : images) {
                System.out.println(file);
            }
        }
    }
}

此示例通过在比较之前将文件名和扩展名都转换为小写来处理大小写不敏感性。构造函数确保扩展名具有前导点。无论文件在文件系统上的实际命名方式如何,此方法都有效。这对于大小写无关紧要的 Windows 系统特别有用。

组合多个过滤器

有时我们需要应用多个过滤条件。此示例展示了如何使用逻辑运算来组合过滤器。我们创建一个复合过滤器,该过滤器在多个过滤器之间应用 AND 和 OR 逻辑。

Main.java
import java.io.File;
import java.io.FilenameFilter;

public class Main {
    
    static class AndFilter implements FilenameFilter {
        private final FilenameFilter filter1;
        private final FilenameFilter filter2;
        
        public AndFilter(FilenameFilter f1, FilenameFilter f2) {
            this.filter1 = f1;
            this.filter2 = f2;
        }
        
        @Override
        public boolean accept(File dir, String name) {
            return filter1.accept(dir, name) && filter2.accept(dir, name);
        }
    }

    public static void main(String[] args) {
        File directory = new File(".");
        
        // Create individual filters
        FilenameFilter javaFilter = (dir, name) -> name.endsWith(".java");
        FilenameFilter prefixFilter = (dir, name) -> name.startsWith("Main");
        
        // Combine filters with AND logic
        FilenameFilter combinedFilter = new AndFilter(javaFilter, prefixFilter);
        
        String[] filteredFiles = directory.list(combinedFilter);
        
        if (filteredFiles != null) {
            System.out.println("Files starting with 'Main' and ending with '.java':");
            for (String file : filteredFiles) {
                System.out.println(file);
            }
        }
    }
}

此示例演示了如何使用组合来组合多个过滤器。AndFilter 类接受两个过滤器,并且仅接受通过这两个过滤器的文件。可以为 OR 或 NOT 逻辑创建类似的类。这种模式在从简单组件构建复杂的过滤需求方面提供了极大的灵活性。

过滤隐藏文件

某些文件系统具有不应包含在正常操作中的隐藏文件。此示例展示了如何在应用其他条件的同时过滤掉隐藏文件。我们将隐藏文件检查与扩展名过滤相结合。

Main.java
import java.io.File;
import java.io.FilenameFilter;

public class Main {
    
    static class VisibleConfigFilter implements FilenameFilter {
        @Override
        public boolean accept(File dir, String name) {
            File file = new File(dir, name);
            return !file.isHidden() && name.endsWith(".cfg");
        }
    }

    public static void main(String[] args) {
        File directory = new File(".");
        
        // Filter for non-hidden config files
        String[] configFiles = directory.list(new VisibleConfigFilter());
        
        if (configFiles != null) {
            System.out.println("Visible config files:");
            for (String file : configFiles) {
                System.out.println(file);
            }
        }
    }
}

此示例检查文件的隐藏状态和扩展名。accept 方法创建一个 File 对象来检查隐藏属性。请注意,隐藏文件检测取决于系统。此方法确保我们只在结果中获得可见的配置文件。

来源

Java FilenameFilter 接口文档

在本文中,我们介绍了 Java FilenameFilter 接口的各个方面。从基本实现到高级过滤技术,这些示例展示了这个简单而强大的接口在文件操作方面的灵活性。

作者

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

列出所有Java教程