将 File.listFiles 与 FileNameExtensionFilter 一起使用

Posted

技术标签:

【中文标题】将 File.listFiles 与 FileNameExtensionFilter 一起使用【英文标题】:Using File.listFiles with FileNameExtensionFilter 【发布时间】:2011-08-10 17:10:16 【问题描述】:

我想获取目录中具有特定扩展名的文件列表。在 API (Java 6) 中,我看到一个方法 File.listFiles(FileFilter) 可以做到这一点。

因为我需要一个特定的扩展,我创建了一个FileNameExtensionFilter。但是,当我使用 listFiles 时出现编译错误。我认为自从FileNameExtensionFilter implements FileFilter 以来,我应该能够做到这一点。代码如下:

FileNameExtensionFilter filter = new FileNameExtensionFilter("text only","txt");
String dir  = "/users/blah/dirname";
File f[] = (new File(dir)).listFiles(filter);

最后一行显示编译错误:

File 类型的方法 listFiles(FileNameFilter) 不适用于 FileNameExtensionFilter 类型的参数

我正在尝试使用listFiles(FileFilter),而不是listFiles(FileNameFilter)。为什么编译器不能识别这个?

如果我编写自己的扩展过滤器扩展 FileFilter,这将有效。我宁愿使用FileNameExtensionFilter 而不是自己写。我做错了什么?

【问题讨论】:

首先,您需要将“txt”作为第一个参数,将“仅文本”作为第二个参数。 代码正确,@lobster1234。见:docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/… 【参考方案1】:

FileNameExtensionFilter 类旨在供 Swing 在 JFileChooser 中使用。

尝试改用FilenameFilter。例如:

File dir = new File("/users/blah/dirname");
File[] files = dir.listFiles(new FilenameFilter() 
    public boolean accept(File dir, String name) 
        return name.toLowerCase().endsWith(".txt");
    
);

【讨论】:

【参考方案2】:

java 8 语法中的单行:

pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));

【讨论】:

可以省略花括号并返回:pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt")); 另一种解决方案:Files.list(Paths.get("your/path")).filter(path -> path.toString().endsWith(".txt")).collect(Collectors.toList());【参考方案3】:

您是否有特定原因要使用FileNameExtensionFilter?我知道这行得通..

private File[] getNewTextFiles() 
    return dir.listFiles(new FilenameFilter() 
        @Override
        public boolean accept(File dir, String name) 
            return name.toLowerCase().endsWith(".txt");
        
    );

【讨论】:

【参考方案4】:

使用 java lambdas(从 java 8 开始可用),您可以在一行中简单地将 javax.swing.filechooser.FileFilter 转换为 java.io.FileFilter

javax.swing.filechooser.FileFilter swingFilter = new FileNameExtensionFilter("jpeg files", "jpeg");
java.io.FileFilter ioFilter = file -> swingFilter.accept(file);
new File("myDirectory").listFiles(ioFilter);

【讨论】:

谢谢,如果您同时需要 filechooser.FileFilterio.FileFilter 但只想定义一次,这将特别有用。【参考方案5】:

Duh.... listFiles 需要 java.io.FileFilter。 FileNameExtensionFilter 扩展 javax.swing.filechooser.FileFilter。我通过实现 java.io.FileFilter 的实例解决了我的问题

编辑:我确实使用了类似于@cFreiner 的答案。我试图使用 Java API 方法而不是编写自己的实现,这就是我尝试使用 FileNameExtensionFilter 的原因。我的应用程序中有很多 FileChoosers,并为此使用了 FileNameExtensionFilters,我错误地认为它也在扩展 java.io.FileFilter。

【讨论】:

【参考方案6】:

这是我快速制作的东西,它的性能应该比 File.getName().endsWith(".xxxx"); 好得多;

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

public class ExtensionsFilter implements FileFilter 

    private char[][] extensions;

    private ExtensionsFilter(String[] extensions)
    
        int length = extensions.length;
        this.extensions = new char[length][];
        for (String s : extensions)
        
            this.extensions[--length] = s.toCharArray();
        
    

    @Override
    public boolean accept(File file)
    
        char[] path = file.getPath().toCharArray();
        for (char[] extension : extensions)
        
            if (extension.length > path.length)
            
                continue;
            
            int pStart = path.length - 1;
            int eStart = extension.length - 1;
            boolean success = true;
            for (int i = 0; i <= eStart; i++)
            
                if ((path[pStart - i] | 0x20) != (extension[eStart - i] | 0x20))
                
                    success = false;
                    break;
                
            
            if (success)
                return true;
        
        return false;
    

以下是各种图像格式的示例。

private static final ExtensionsFilter IMAGE_FILTER = 
      new ExtensionsFilter(new String[] ".png", ".jpg", ".bmp");

【讨论】:

好,但我的新口号是保持简单,除非它们需要更复杂,也就是说,除非我真的必须自己编写,否则使用 Java API 方法/类。 @JeremyTrifilo 你为什么做了 path[pStart - i] | 0x20 在代码中? 为什么要重新发明***? 该 | 20 用于大写与小写的变体。它强制将 32 添加到字母,使其成为小写字母以进行检查。因此,您可以将文件另存为 Example.PnG 或 Example.pNg,它仍然会拾取它。我通常不会重做这样的事情,但我这样做是因为如果你能理解这些事情是如何工作的,以及可以做些什么来让它们变得更好,那将是很好的学习。但是我明白你的意思,因为性能提升很小,所以对于这种情况来说它是多余的,并且不需要快速。

以上是关于将 File.listFiles 与 FileNameExtensionFilter 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

File.listFiles() 使用 JDK 6 破坏 unicode 名称(Unicode 规范化问题)

如何在 Java 7 中用 nio 替换 File.listFiles(FileFilter filter)?

如何按字母顺序 File.listFiles?

我如何使用 file.listFiles() 来列出子目录和文件

file.listFiles()按文件大小名称日期排序方法

java file.listFiles()按文件名称日期大小排序