Verwenden von File.listFiles mit FileNameExtensionFilter

82

Ich möchte eine Liste von Dateien mit einer bestimmten Erweiterung in einem Verzeichnis erhalten. In der API (Java 6) sehe ich eine Methode, File.listFiles(FileFilter)die dies tun würde.

Da ich eine bestimmte Erweiterung benötige, habe ich eine erstellt FileNameExtensionFilter. Ich erhalte jedoch einen Kompilierungsfehler, wenn ich damit verwende listFiles. Ich ging davon aus, dass FileNameExtensionFilter implements FileFilterich dies seitdem tun sollte. Code folgt:

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

Die letzte Zeile zeigt einen Kompilierungsfehler:

Die Methode listFiles (FileNameFilter) vom Typ File gilt nicht für Argumente vom Typ FileNameExtensionFilter

Ich versuche zu benutzen listFiles(FileFilter), nicht listFiles(FileNameFilter). Warum erkennt der Compiler dies nicht?

Dies funktioniert, wenn ich meinen eigenen Erweiterungsfilter schreibe FileFilter. Ich würde lieber FileNameExtensionFiltermeine eigenen verwenden als schreiben. Was mache ich falsch?

Anu
quelle
Zunächst müssen Sie "txt" als erstes Argument und "nur Text" als zweites Argument haben.
Hummer1234
Der Code ist korrekt, @ lobster1234. Siehe: docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/…
james.garriss

Antworten:

182

Die FileNameExtensionFilterKlasse ist für die Verwendung von Swing in a vorgesehen JFileChooser.

Versuchen Sie FilenameFilterstattdessen ein. Zum Beispiel:

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
quelle
37

Einzeiler in Java 8-Syntax:

pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
Serġan
quelle
7
Sie können geschweifte Klammern weglassen und zurückkehren:pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
Gabor Szarnyas
Eine andere Lösung:Files.list(Paths.get("your/path")).filter(path -> path.toString().endsWith(".txt")).collect(Collectors.toList());
CeePlusPlus
28

Gibt es einen bestimmten Grund, den Sie verwenden möchten FileNameExtensionFilter? Ich weiß, dass das funktioniert ..

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

Duh .... listFiles benötigt java.io.FileFilter. FileNameExtensionFilter erweitert javax.swing.filechooser.FileFilter. Ich habe mein Problem durch die Implementierung einer Instanz von java.io.FileFilter gelöst

Bearbeiten: Ich habe etwas Ähnliches wie die Antwort von @ cFreiner verwendet. Ich habe versucht, eine Java-API-Methode zu verwenden, anstatt meine eigene Implementierung zu schreiben, weshalb ich versucht habe, FileNameExtensionFilter zu verwenden. Ich habe viele FileChooser in meiner Anwendung und habe dafür FileNameExtensionFilters verwendet, und ich habe fälschlicherweise angenommen, dass es auch java.io.FileFilter erweitert.

Anu
quelle
1

Hier ist etwas, das ich schnell gemacht habe und das weitaus besser funktionieren sollte als 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;
    }
}

Hier ist ein Beispiel für verschiedene Bildformate.

private static final ExtensionsFilter IMAGE_FILTER = 
      new ExtensionsFilter(new String[] {".png", ".jpg", ".bmp"});
Jeremy Trifilo
quelle
10
Gut, aber mein neues Mantra ist es, die Dinge einfach zu halten, es sei denn, sie müssen komplizierter sein, dh Java-API-Methoden / -Klassen verwenden, es sei denn, ich muss wirklich meine eigenen schreiben.
Anu
@JeremyTrifilo Warum hast du Pfad [pStart - i] | gemacht? 0x20 im Code?
Sohil
1
Warum das Rad neu erfinden?
James.garriss
Die | 20 war für Groß- und Kleinbuchstaben. Der Buchstabe wird mit 32 addiert, was ihn zu einem Kleinbuchstaben für die Überprüfung macht. Sie könnten also eine Datei als Example.PnG oder Example.pNg speichern und sie würde sie trotzdem abholen. Normalerweise mache ich solche Sachen nicht noch einmal, aber ich mache es, weil es toll ist zu lernen, ob man verstehen kann, wie diese Dinge funktionieren und was getan werden kann, um sie besser zu machen. Ich verstehe jedoch, was Sie meinen, dass es für dieses Szenario redundant ist, da die Leistungssteigerung minimal ist und es nicht erforderlich ist, dass dies schnell erfolgt.
Jeremy Trifilo
1

Mit Java lambdas (verfügbar seit Java - 8) können Sie einfach konvertieren javax.swing.filechooser.FileFilterzu java.io.FileFilterin einer Zeile.

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
quelle