Использование File.listFiles с FileNameExtensionFilter

84

Я хочу получить список файлов с определенным расширением в каталоге. В 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);

Последняя строка показывает ошибку компиляции:

метод listFiles (FileNameFilter) в типе File не применяется для аргументов типа FileNameExtensionFilter

Я пытаюсь использовать listFiles(FileFilter), а не listFiles(FileNameFilter). Почему компилятор этого не распознает?

Это работает, если я напишу свой собственный фильтр расширения FileFilter. Я лучше буду использовать, FileNameExtensionFilterчем писать свой собственный. Что я делаю неправильно?

Ану
источник
Во-первых, вам нужно иметь «txt» в качестве первого аргумента и «только текст» в качестве второго.
lobster1234
Код правильный, @ lobster1234. См .: docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/…
james.garriss

Ответы:

184

FileNameExtensionFilterКласс предназначен для свинга , чтобы использовать в 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");
    }
});
БелыйКлык34
источник
38

Однострочный синтаксис java 8:

pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
Серджан
источник
7
Вы можете опустить фигурные скобки и вернуть:pdfTestDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".txt"));
Габор Сарняс,
Другое решение:Files.list(Paths.get("your/path")).filter(path -> path.toString().endsWith(".txt")).collect(Collectors.toList());
CeePlusPlus
28

Есть ли конкретная причина, по которой вы хотите использовать FileNameExtensionFilter? Я знаю, что это работает ..

private File[] getNewTextFiles() {
    return dir.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File dir, String name) {
            return name.toLowerCase().endsWith(".txt");
        }
    });
}
CFreiner
источник
1

Да .... listFiles требует java.io.FileFilter. FileNameExtensionFilter расширяет javax.swing.filechooser.FileFilter. Я решил свою проблему, реализовав экземпляр java.io.FileFilter

Изменить: я использовал что-то похожее на ответ @ cFreiner. Я пытался использовать метод Java API вместо написания собственной реализации, поэтому я пытался использовать FileNameExtensionFilter. В моем приложении есть много FileChoosers, и я использовал для этого FileNameExtensionFilters, и я ошибочно предположил, что он также расширяет java.io.FileFilter.

Ану
источник
1

Вот кое-что, что я сделал быстро, и он должен работать намного лучше, чем File.getName () .ndsWith (". 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"});
Джереми Трифило
источник
10
Хорошо, но моя новая мантра - делать вещи простыми, если они не должны быть более сложными, то есть использовать методы / классы Java API, если мне действительно не нужно писать свои собственные.
Anu
@JeremyTrifilo Почему вы сделали путь [pStart - i] | 0x20 в коде?
Sohil
1
Зачем изобретать велосипед?
james.garriss
| 20 было для вариантов прописных и строчных букв. Он принудительно добавляет 32 к букве, что делает ее строчной буквой для проверки. Таким образом, вы можете сохранить файл как Example.PnG или Example.pNg, и он все равно заберет его. Обычно я не переделываю подобные вещи, но я делаю это, потому что это отличное обучение, если вы понимаете, как эти вещи работают и что можно сделать, чтобы их улучшить. Однако я понимаю, что вы имеете в виду, что это избыточно для этого сценария, поскольку повышение производительности минимально, и нет необходимости в том, чтобы это было быстро.
Джереми Трифило
1

С помощью 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);
Марчин Микосик
источник