Usando File.listFiles con FileNameExtensionFilter

82

Me gustaría obtener una lista de archivos con una extensión específica en un directorio. En la API (Java 6), veo un método File.listFiles(FileFilter)que haría esto.

Como necesito una extensión específica, creé un FileNameExtensionFilter. Sin embargo, obtengo un error de compilación cuando lo uso listFilescon esto. Supuse que FileNameExtensionFilter implements FileFilter, desde entonces , debería poder hacer esto. El código sigue:

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

La última línea muestra un error de compilación:

El método listFiles (FileNameFilter) en tipo File no es aplicable para argumentos de tipo FileNameExtensionFilter

Estoy tratando de usar listFiles(FileFilter), no listFiles(FileNameFilter). ¿Por qué el compilador no reconoce esto?

Esto funciona si escribo mi propio filtro de extensión extendiendo FileFilter. Prefiero usar FileNameExtensionFilterque escribir el mío. ¿Qué estoy haciendo mal?

Anu
fuente
En primer lugar, debe tener "txt" como primer argumento y "solo texto" como segundo.
langosta1234
El código es correcto, @ lobster1234. Ver: docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/…
james.garriss

Respuestas:

182

La FileNameExtensionFilterclase está pensada para que Swing se utilice en a JFileChooser.

Intente usar un FilenameFilteren su lugar. Por ejemplo:

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");
    }
});
WhiteFang34
fuente
37

Una línea en la sintaxis de Java 8:

pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
Serġan
fuente
7
Puede omitir las llaves y devolver:pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
Gabor Szarnyas
Otra solución:Files.list(Paths.get("your/path")).filter(path -> path.toString().endsWith(".txt")).collect(Collectors.toList());
CeePlusPlus
28

¿Existe una razón específica por la que desea utilizar FileNameExtensionFilter? Sé que esto funciona ...

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

Duh .... listFiles requiere java.io.FileFilter. FileNameExtensionFilter extiende javax.swing.filechooser.FileFilter. Resolví mi problema implementando una instancia de java.io.FileFilter

Editar: Usé algo similar a la respuesta de @ cFreiner. Estaba tratando de usar un método de API de Java en lugar de escribir mi propia implementación, por eso estaba tratando de usar FileNameExtensionFilter. Tengo muchos FileChoosers en mi aplicación y he usado FileNameExtensionFilters para eso y asumí erróneamente que también estaba extendiendo java.io.FileFilter.

Anu
fuente
1

Aquí hay algo que acabo de hacer rápidamente y debería funcionar mucho mejor que 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;
    }
}

A continuación, se muestra un ejemplo de varios formatos de imágenes.

private static final ExtensionsFilter IMAGE_FILTER = 
      new ExtensionsFilter(new String[] {".png", ".jpg", ".bmp"});
Jeremy Trifilo
fuente
10
Bien, pero mi nuevo mantra es mantener las cosas simples a menos que necesiten ser más complicadas, es decir, usar métodos / clases de API de Java a menos que realmente tenga que escribir el mío.
Anu
@JeremyTrifilo ¿Por qué has hecho ruta [pStart - i] | 0x20 en el código?
Sohil
1
¿Por qué reinventar la rueda?
james.garriss
El | 20 fue para variaciones en mayúsculas frente a minúsculas. Fuerza agrega 32 a la letra, lo que la convierte en una letra minúscula para verificar. Por lo tanto, podría guardar un archivo como Example.PnG o Example.pNg y aún lo recogería. Normalmente no rehago cosas como esta, pero lo hago porque es un gran aprendizaje si puedes entender cómo funcionan estas cosas y qué se puede hacer para mejorarlas. Sin embargo, entiendo lo que quiere decir que es redundante para este escenario, ya que el aumento de rendimiento es mínimo y no es necesario que esto sea rápido.
Jeremy Trifilo
1

Con java lambdas (disponible desde java 8), simplemente puede convertir javax.swing.filechooser.FileFiltera java.io.FileFilteren una línea.

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