Korzystanie z File.listFiles z FileNameExtensionFilter

83

Chciałbym uzyskać listę plików z określonym rozszerzeniem w katalogu. W API (Java 6) widzę metodę, File.listFiles(FileFilter)która by to zrobiła.

Ponieważ potrzebuję określonego rozszerzenia, utworzyłem plik FileNameExtensionFilter. Jednak pojawia się błąd kompilacji, gdy używam listFilestego. Założyłem, że od tego czasu FileNameExtensionFilter implements FileFilterpowinienem być w stanie to zrobić. Kod następujący:

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

Ostatnia linia pokazuje błąd kompilacji:

method listFiles (FileNameFilter) w typie File nie ma zastosowania dla argumentów typu FileNameExtensionFilter

Próbuję użyć listFiles(FileFilter), nie listFiles(FileNameFilter). Dlaczego kompilator tego nie rozpoznaje?

Działa to, jeśli napiszę własny rozszerzający filtr rozszerzenia FileFilter. Wolałbym używać FileNameExtensionFilterniż pisać własne. Co ja robię źle?

Anu
źródło
Po pierwsze, musisz mieć „txt” jako pierwszy argument i „tylko tekst” jako drugi.
homar 1234
Kod jest poprawny, @ lobster1234. Zobacz: docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/…
james.garriss

Odpowiedzi:

183

FileNameExtensionFilterKlasa jest przeznaczona dla Swing być stosowany w JFileChooser.

Spróbuj FilenameFilterzamiast tego użyć . Na przykład:

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
źródło
38

Jednowierszowy w składni Java 8:

pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
Serġan
źródło
7
Możesz pominąć pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
aparat
Inne rozwiązanie:Files.list(Paths.get("your/path")).filter(path -> path.toString().endsWith(".txt")).collect(Collectors.toList());
CeePlusPlus
28

Czy jest jakiś konkretny powód, dla którego chcesz użyć FileNameExtensionFilter? Wiem, że to działa ...

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

Duh .... listFiles wymaga java.io.FileFilter. FileNameExtensionFilter rozszerza javax.swing.filechooser.FileFilter. Rozwiązałem swój problem, implementując instancję java.io.FileFilter

Edycja: użyłem czegoś podobnego do odpowiedzi @ cFreiner. Próbowałem użyć metody Java API zamiast pisać własną implementację, dlatego próbowałem użyć FileNameExtensionFilter. Mam wiele FileChoosers w mojej aplikacji i użyłem do tego FileNameExtensionFilters i błędnie założyłem, że rozszerzał również java.io.FileFilter.

Anu
źródło
1

Oto coś, co szybko stworzyłem i powinno działać znacznie lepiej niż File.getName (). EndWith (". 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;
    }
}

Oto przykład dla różnych formatów obrazów.

private static final ExtensionsFilter IMAGE_FILTER = 
      new ExtensionsFilter(new String[] {".png", ".jpg", ".bmp"});
Jeremy Trifilo
źródło
10
Dobrze, ale moja nowa mantra polega na tym, aby wszystko było proste, chyba że muszą być bardziej skomplikowane, co oznacza, że ​​używam metod / klas Java API, chyba że naprawdę muszę napisać własne.
Anu
@JeremyTrifilo Dlaczego wykonałeś ścieżkę [pStart - i] | 0x20 w kodzie?
Sohil
1
Po co odkrywać koło na nowo?
james.garriss
| 20 było dla odmian wielkich i małych liter. Wymusza dodanie 32 do litery, co czyni ją małą literą do sprawdzenia. Możesz więc zapisać plik jako Example.PnG lub Example.pNg i nadal go odbierał. Zwykle nie powtarzam takich rzeczy, ale robię to, ponieważ świetnie się uczy, jeśli możesz zrozumieć, jak te rzeczy działają i co można zrobić, aby je ulepszyć. Rozumiem jednak, co masz na myśli, jest to zbędne w tym scenariuszu, ponieważ wzrost wydajności jest minimalny i nie ma potrzeby, aby to było szybkie.
Jeremy Trifilo,
1

Z lambdami java (dostępnymi od java 8) możesz po prostu przekonwertować javax.swing.filechooser.FileFilterje java.io.FileFilterw jednej linii.

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
źródło