Рекурсивный список файлов в Java

Как мне рекурсивно перечислить все файлы в каталоге в Java? Предоставляет ли фреймворк какую-либо полезность?

Я видел много хакерских реализаций. Но ни один из фреймворков или nio


person Quintin Par    schedule 13.01.2010    source источник
comment
Я только что завершил Результаты тестирования, которые предоставляют тесты производительности для многих ответов. Неудивительно, что все ответы на основе NIO работают лучше всего. Ответ Commons-io - явно худший с вдвое большей длиной тиража.   -  person Brett Ryan    schedule 29.06.2015
comment
Java8: Files.walk?   -  person Benj    schedule 04.10.2016


Ответы (26)


Java 8 предоставляет удобный поток для обработки всех файлов в дереве.

Files.walk(Paths.get(path))
        .filter(Files::isRegularFile)
        .forEach(System.out::println);

Это обеспечивает естественный способ просмотра файлов. Поскольку это поток, вы можете выполнять все хорошие операции с потоком над результатом, такие как ограничение, группировка, сопоставление, ранний выход и т. Д.

ОБНОВЛЕНИЕ: я мог бы указать, что есть также Files.find, который принимает BiPredicate, который может быть более эффективным, если вам нужно проверить атрибуты файла.

Files.find(Paths.get(path),
           Integer.MAX_VALUE,
           (filePath, fileAttr) -> fileAttr.isRegularFile())
        .forEach(System.out::println);

Обратите внимание, что, хотя JavaDoc ускользает от того, что этот метод может быть более эффективным, чем Files.walk фактически идентичен, разницу в производительности можно наблюдать, если вы также получаете файл атрибуты в вашем фильтре. В конце, если вам нужно отфильтровать атрибуты, используйте Files.find, в противном случае используйте Files.walk, в основном потому, что есть перегрузки и так удобнее.

ИСПЫТАНИЯ. По запросу я предоставил сравнение производительности многих ответов. Ознакомьтесь с проектом Github, который содержит результаты и тестовый пример.

person Brett Ryan    schedule 03.06.2014
comment
Один из тех примеров, который может показать магию функционального программирования даже новичку. - person Johnny; 15.01.2015
comment
Как производительность этого метода по сравнению с методами до Java 8? Мой текущий обход каталога слишком медленный, и я ищу что-нибудь, что его ускорит. - person Sridhar Sarnobat; 26.06.2015
comment
Я пишу несколько тестов, содержащих большинство вариантов в предоставленных ответах. Пока что кажется, что использование Files.walk с параллельным потоком является лучшим, за ним следует Files.walkFileTree, который лишь незначительно медленнее. Принятый ответ с использованием commons-io, безусловно, самый медленный по моим тестам, он в 4 раза медленнее. - person Brett Ryan; 28.06.2015
comment
Тесты завершены, и проект добавлен в Github, проверьте его результаты. Короткий ответ - используйте любой вариант NIO из предоставленных ответов. - person Brett Ryan; 29.06.2015
comment
@BrettRyan, я пробовал ваше решение, но получаю исключение Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException. Как я мог это исправить - person Kachna; 05.09.2015
comment
Как мне получить из этого фактический список файлов? - person thouliha; 09.10.2015
comment
@thouliha вместо forEach используйте collect с набором или сборщиком списков, например .collect(Collectors.toList()). Если вы можете избежать использования коллектора в своей логике, тем лучше, поскольку вы будете использовать меньше объектов и обработка будет быстрее. - person Brett Ryan; 10.10.2015
comment
Вау, не могу отвести глаз от этого прекрасного кода. Кто бы мог подумать, что когда-нибудь Java позволит реализовать такие операции в одну строку. - person jFrenetic; 24.01.2016
comment
@BrettRyan, я прав, что по умолчанию Files.walk () не следует по символическим ссылкам? Если это так и кто-то хочет следовать символическим ссылкам, похоже, что первым фрагментом кода может быть Files.walk(Paths.get(path), FileVisitOption.FOLLOW_LINKS) - person Matt Passell; 03.03.2016
comment
Приносим извинения за задержку с ответом @MattPassell, вы правы. При обнаружении круговой ссылки следует использовать это с осторожностью, вы не получите рекурсивного цикла, хотя, к сожалению, получите FileSystemLoopException, который заключен в UncheckedIOException - person Brett Ryan; 11.03.2016
comment
@BrettRyan, спасибо, хорошее замечание. В конкретном месте, где я его использую, начальный путь может быть символической ссылкой, но с этого момента это не так. Это позволило мне сделать что-то вроде этого Path basePath = Files.isSymbolicLink(basePath) ? Files.readSymbolicLink(basePath) : basePath;, а затем пройти по дереву, не переходя по ссылкам. :) - person Matt Passell; 11.03.2016
comment
@BrettRyan вместо forEach use collect Извините, но мне все еще неясно. Вызов .collect(stagingFileList::add) в результирующем потоке из этого кода дает мне Collector<Path,A,R> is not a functional interface в параметре сбора. Этот стрим - это круто, но я не совсем уверен, что я ищу, чтобы это исправить. - person Amalgovinus; 13.01.2017
comment
Это то, что я пытаюсь ... Files.find( Paths.get(path), Integer.MAX_VALUE, (filePath, fileAttr) -> fileAttr.isRegularFile()) .collect(list::add); - person Amalgovinus; 13.01.2017
comment
@Amalgovinus то, что вы ищете, - это коллекционер, а вы дали ссылку на метод. Заменить list :: добавить на Collectors.toList() - person Brett Ryan; 13.01.2017
comment
Остерегайтесь этой проблемы: bugs.openjdk.java.net/browse/JDK-8039910 Дополнительная информация здесь: stackoverflow.com/questions/ 22867286 / - person Jonathan Hult; 16.01.2017
comment
Files.walk выглядит красиво, но довольно часто бесполезно ... выдает исключение, если у вас нет доступа даже к одному файлу ... и у вас ничего нет ... - person razor; 22.11.2018
comment
@BrettRyan - Что означает, что директория открыта, что требует ее закрытия? javadoc говорит, что нужно поместить walk () и find () в блок try-with-resources. Я никогда не слышал о концепции открытого каталога - person Vahid Pazirandeh; 01.04.2020

FileUtils иметь _ 1_ и _ 2_. Дайте им попробовать. (из commons-io)

Изменить: вы можете проверить здесь тест различных подходов. Кажется, что подход commons-io медленный, поэтому выберите несколько более быстрых отсюда (если это важно)

person Bozho    schedule 13.01.2010
comment
К сведению: если вы просто хотите перечислить все файлы рекурсивно без фильтрации, сделайте FileUtils.listFiles(dir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE), где dir - это объект File, указывающий на базовый каталог. - person andronikus; 27.04.2012
comment
Вы можете рассмотреть возможность использования listFilesAndDirs(), поскольку listFiles() не возвращает пустые папки. - person schnatterer; 14.02.2014
comment
@MikeFHay Глядя на код FileUtils, я думаю, что это могло быть FileUtils.listFiles(dir, true, true). использование FileUtils.listFiles(dir, null, true) вызовет исключение, а FileUtils.listFiles(dir, true, null) выведет список всех файлов без просмотра подкаталогов. - person ocramot; 23.05.2014
comment
Как насчет собственной библиотеки JDK? Я могу легко реализовать это, но я бы просто был C&P из других мест. - person Christian Bongiorno; 18.09.2014
comment
Я собираю несколько тестов, но пока кажется, что это в 4 раза медленнее, чем при использовании альтернатив JDK8 или JDK7. Символические ссылки также оказываются проблематичными с этим подходом, особенно когда они ссылаются на каталоги выше в дереве, это приводит к тому, что метод никогда не возвращается, этого можно избежать, обрабатывая фильтр, но, к сожалению, сами символические ссылки не посещаются, даже если файл. - person Brett Ryan; 28.06.2015

// Готов к запуску

import java.io.File;

public class Filewalker {

    public void walk( String path ) {

        File root = new File( path );
        File[] list = root.listFiles();

        if (list == null) return;

        for ( File f : list ) {
            if ( f.isDirectory() ) {
                walk( f.getAbsolutePath() );
                System.out.println( "Dir:" + f.getAbsoluteFile() );
            }
            else {
                System.out.println( "File:" + f.getAbsoluteFile() );
            }
        }
    }

    public static void main(String[] args) {
        Filewalker fw = new Filewalker();
        fw.walk("c:\\" );
    }

}
person stacker    schedule 13.01.2010
comment
Просто помните, что для символических ссылок, которые указывают на путь выше в иерархии путей, метод никогда не закончится. Рассмотрим путь с символической ссылкой, указывающей на -> .. - person Brett Ryan; 28.06.2015
comment
По сути, это плохая реализация Files.walkFileTree. Я бы порекомендовал, чтобы люди смотрели на FIles.walkFileTree вместо того, чтобы пытаться свернуть его самостоятельно ... У него есть обработка для точной проблемы, на которую указал @BrettRyan. - person Tyler Nichols; 19.06.2018
comment
Благодарим вас за включение import java.io.File ;. Так много примеров забывают включить материал пространства имен или даже материал типа данных, что делает пример отправной точкой в ​​путешествии открытий. Вот этот пример готов к запуску. Спасибо. - person barrypicker; 14.07.2019
comment
Путь может отличаться в зависимости от того, где находится файл Filewalker. Используйте _1 _, _ 2_ или "../" для корневого каталога, текущего рабочего каталога и родительского каталога соответственно - person Moses Kirathe; 14.06.2020

В Java 7 будет есть Files.walkFileTree:

Если вы укажете начальную точку и посетителя файла, он будет вызывать различные методы для посетителя файла при просмотре файла в дереве файлов. Мы ожидаем, что люди будут использовать это, если они разрабатывают рекурсивную копию, рекурсивное перемещение, рекурсивное удаление или рекурсивную операцию, которая устанавливает разрешения или выполняет другую операцию с каждым из файлов.

Теперь существует целое руководство Oracle по этому вопросу.

person yawn    schedule 13.01.2010
comment
И он никогда не сообщает об окончании прогулки. - person Farid; 15.06.2020

Никаких внешних библиотек не требуется.
Возвращает коллекцию, чтобы вы могли делать с ней все, что захотите, после звонка.

public static Collection<File> listFileTree(File dir) {
    Set<File> fileTree = new HashSet<File>();
    if(dir==null||dir.listFiles()==null){
        return fileTree;
    }
    for (File entry : dir.listFiles()) {
        if (entry.isFile()) fileTree.add(entry);
        else fileTree.addAll(listFileTree(entry));
    }
    return fileTree;
}
person Petrucio    schedule 25.07.2012

Я бы сказал что-то вроде:

public void list(File file) {
    System.out.println(file.getName());
    File[] children = file.listFiles();
    for (File child : children) {
        list(child);
    }
}

System.out.println нужен только для того, чтобы указать, что с файлом нужно что-то делать. нет необходимости различать файлы и каталоги, поскольку у нормального файла просто нет дочерних элементов.

person Stefan Schmidt    schedule 13.01.2010
comment
Из документации listFiles(): «Если это абстрактное имя пути не обозначает каталог, то этот метод возвращает null». - person hfs; 17.11.2011
comment
Улучшенный вариант общедоступной статической коллекции ‹File› listFileTree (каталог файлов) {if (null == каталог ||! Dir.isDirectory ()) {return Collections.emptyList (); } окончательный набор ‹File› fileTree = new HashSet ‹File› (); для (Запись файла: dir.listFiles ()) {если (запись.isFile ()) {fileTree.add (запись); } еще {fileTree.addAll (listFileTree (запись)); }} return fileTree; } - person Ben; 23.11.2013
comment
Для меня это наиболее краткий и рекурсивный ответ. - person WillieT; 31.05.2018

Я предпочитаю использовать очередь рекурсии для такого простого обхода:

List<File> allFiles = new ArrayList<File>();
Queue<File> dirs = new LinkedList<File>();
dirs.add(new File("/start/dir/"));
while (!dirs.isEmpty()) {
  for (File f : dirs.poll().listFiles()) {
    if (f.isDirectory()) {
      dirs.add(f);
    } else if (f.isFile()) {
      allFiles.add(f);
    }
  }
}
person benroth    schedule 30.05.2012
comment
Но ваш алгоритм не может печатать с отступом. Каталоги и файлы перепутаны. Любое решение? - person Wei; 01.02.2013

просто напишите это самостоятельно, используя простую рекурсию:

public List<File> addFiles(List<File> files, File dir)
{
    if (files == null)
        files = new LinkedList<File>();

    if (!dir.isDirectory())
    {
        files.add(dir);
        return files;
    }

    for (File file : dir.listFiles())
        addFiles(files, file);
    return files;
}
person pstanton    schedule 13.01.2010
comment
Пожалуйста! позвольте вызывающей стороне инициализировать список файлов, чтобы ему не приходилось каждый раз проверять его нулевое значение. Если вы хотите создать второй (общедоступный) метод, который создает список, вызывает этот внутренний метод и возвращает полный список. - person helios; 13.01.2010
comment
что бы ни. нулевая проверка не очень дорогая, удобство + личные предпочтения в стороне, я думаю, он поймет суть. - person pstanton; 13.01.2010
comment
Не могли бы вы объяснить более подробно? - person uday; 31.01.2013

В Java 7 вы можете использовать следующий класс:

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

public class MyFileIterator extends SimpleFileVisitor<Path>
{
    public MyFileIterator(String path) throws Exception
    {
        Files.walkFileTree(Paths.get(path), this);
    }

    @Override
    public FileVisitResult visitFile(Path file,
            BasicFileAttributes attributes) throws IOException
    {
        System.out.println("File: " + file);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir,
            BasicFileAttributes attributes) throws IOException
    {
        System.out.println("Dir: " + dir);
        return FileVisitResult.CONTINUE;
    }
}
person chao    schedule 22.11.2014

Я думаю, это должно работать:

File dir = new File(dirname);
String[] files = dir.list();

Таким образом, у вас есть файлы и каталоги. Теперь используйте рекурсию и сделайте то же самое для каталогов (класс File имеет метод isDirectory()).

person Michał Niklas    schedule 13.01.2010
comment
Использование рекурсии бесполезно. Должен быть пример того, как. - person Ginger McMurray; 10.07.2020

В Java 8 теперь мы можем использовать утилиту Files для просмотра дерева файлов. Очень простой.

Files.walk(root.toPath())
      .filter(path -> !Files.isDirectory(path))
      .forEach(path -> System.out.println(path));
person Roy Kachouh    schedule 05.10.2014

Этот код готов к запуску

public static void main(String... args) {
    File[] files = new File("D:/").listFiles();
    if (files != null) 
       getFiles(files);
}

public static void getFiles(File[] files) {
    for (File file : files) {
        if (file.isDirectory()) {
            getFiles(file.listFiles());
        } else {
            System.out.println("File: " + file);
        }
    }
}
person Ebraheem Alrabeea    schedule 30.10.2017

Помимо рекурсивного обхода, можно также использовать подход, основанный на посетителях.

В приведенном ниже коде для обхода используется подход, основанный на посетителях. Ожидается, что входными данными для программы будет корневой каталог для обхода.

public interface Visitor {
    void visit(DirElement d);
    void visit(FileElement f);
}

public abstract class Element {
    protected File rootPath;
    abstract void accept(Visitor v);

    @Override
    public String toString() {
        return rootPath.getAbsolutePath();
    }
}

public class FileElement extends Element {
    FileElement(final String path) {
        rootPath = new File(path);
    }

    @Override
    void accept(final Visitor v) {
        v.visit(this);
    }
}

public class DirElement extends Element implements Iterable<Element> {
    private final List<Element> elemList;
    DirElement(final String path) {
        elemList = new ArrayList<Element>();
        rootPath = new File(path);
        for (File f : rootPath.listFiles()) {
            if (f.isDirectory()) {
                elemList.add(new DirElement(f.getAbsolutePath()));
            } else if (f.isFile()) {
                elemList.add(new FileElement(f.getAbsolutePath()));
            }
        }
    }

    @Override
    void accept(final Visitor v) {
        v.visit(this);
    }

    public Iterator<Element> iterator() {
        return elemList.iterator();
    }
}

public class ElementWalker {
    private final String rootDir;
    ElementWalker(final String dir) {
        rootDir = dir;
    }

    private void traverse() {
        Element d = new DirElement(rootDir);
        d.accept(new Walker());
    }

    public static void main(final String[] args) {
        ElementWalker t = new ElementWalker("C:\\temp");
        t.traverse();
    }

    private class Walker implements Visitor {
        public void visit(final DirElement d) {
            System.out.println(d);
            for(Element e:d) {
                e.accept(this);
            }
        }

        public void visit(final FileElement f) {
            System.out.println(f);
        }
    }
}
person sateesh    schedule 13.01.2010

Вы можете использовать приведенный ниже код, чтобы рекурсивно получить список файлов определенной папки или каталога.

public static void main(String args[]) {

        recusiveList("D:");

    }

    public static void recursiveList(String path) {

        File f = new File(path);
        File[] fl = f.listFiles();
        for (int i = 0; i < fl.length; i++) {
            if (fl[i].isDirectory() && !fl[i].isHidden()) {
                System.out.println(fl[i].getAbsolutePath());
                recusiveList(fl[i].getAbsolutePath());
            } else {
                System.out.println(fl[i].getName());
            }
        }
    }
person Rakesh Chaudhari    schedule 23.06.2017

Перечисляет все файлы с предоставленными расширениями, с возможностью сканирования вложенных папок (рекурсивно)

 public static ArrayList<File> listFileTree(File dir,boolean recursive) {
        if (null == dir || !dir.isDirectory()) {
            return new ArrayList<>();
        }
        final Set<File> fileTree = new HashSet<File>();
        FileFilter fileFilter = new FileFilter() {
            private final String[] acceptedExtensions = new String[]{"jpg", "png", "webp", "jpeg"};

            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }
                for (String extension : acceptedExtensions) {
                    if (file.getName().toLowerCase().endsWith(extension)) {
                        return true;
                    }
                }
                return false;
            }
        };
        File[] listed = dir.listFiles(fileFilter);
        if(listed!=null){
            for (File entry : listed) {
                if (entry.isFile()) {
                    fileTree.add(entry);
                } else if(recursive){
                    fileTree.addAll(listFileTree(entry,true));
                }
            }
        }
        return new ArrayList<>(fileTree);
    }
person Omkar    schedule 21.09.2020

Нерекурсивная BFS с одним списком (конкретный пример - поиск файлов * .eml):

    final FileFilter filter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            return file.isDirectory() || file.getName().endsWith(".eml");
        }
    };

    // BFS recursive search
    List<File> queue = new LinkedList<File>();
    queue.addAll(Arrays.asList(dir.listFiles(filter)));

    for (ListIterator<File> itr = queue.listIterator(); itr.hasNext();) {
        File file = itr.next();
        if (file.isDirectory()) {
            itr.remove();
            for (File f: file.listFiles(filter)) itr.add(f);
        }
    }
person bobah    schedule 22.09.2013

Моя версия (конечно, я мог бы использовать встроенную прогулку в Java 8 ;-)):

public static List<File> findFilesIn(File rootDir, Predicate<File> predicate) {
        ArrayList<File> collected = new ArrayList<>();
        walk(rootDir, predicate, collected);
        return collected;
    }

    private static void walk(File dir, Predicate<File> filterFunction, List<File> collected) {
        Stream.of(listOnlyWhenDirectory(dir))
                .forEach(file -> walk(file, filterFunction, addAndReturn(collected, file, filterFunction)));
    }

    private static File[] listOnlyWhenDirectory(File dir) {
        return dir.isDirectory() ? dir.listFiles() : new File[]{};
    }

    private static List<File> addAndReturn(List<File> files, File toAdd, Predicate<File> filterFunction) {
        if (filterFunction.test(toAdd)) {
            files.add(toAdd);
        }
        return files;
    }
person user1189332    schedule 08.11.2015

Вот простое, но отлично работающее решение с использованием recursion:

public static List<Path> listFiles(String rootDirectory)
{
    List<Path> files = new ArrayList<>();
    listFiles(rootDirectory, files);

    return files;
}

private static void listFiles(String path, List<Path> collectedFiles)
{
    File root = new File(path);
    File[] files = root.listFiles();

    if (files == null)
    {
        return;
    }

    for (File file : files)
    {
        if (file.isDirectory())
        {
            listFiles(file.getAbsolutePath(), collectedFiles);
        } else
        {
            collectedFiles.add(file.toPath());
        }
    }
}
person BullyWiiPlaza    schedule 01.01.2018

Я придумал это для рекурсивной печати всех файлов / имен файлов.

private static void printAllFiles(String filePath,File folder) {
    if(filePath==null) {
        return;
    }
    File[] files = folder.listFiles();
    for(File element : files) {
        if(element.isDirectory()) {
            printAllFiles(filePath,element);
        } else {
            System.out.println(" FileName "+ element.getName());
        }
    }
}
person kanaparthikiran    schedule 02.08.2019

В Kotlin есть FileTreeWalk для этого. Например:

dataDir.walkTopDown().filter { !it.isDirectory }.joinToString("\n") {
   "${it.toRelativeString(dataDir)}: ${it.length()}"
}

Создает текстовый список всех файлов, не являющихся каталогами, в заданном корне, по одному файлу в строке с путем относительно корня и длиной.

person Clyde    schedule 10.12.2019

принятый ответ великолепен, однако он не работает, когда вы хотите выполнить ввод-вывод внутри лямбда.

Вот что вы можете сделать, если ваше действие объявляет исключения IOExceptions.

Вы можете рассматривать отфильтрованный поток как Iterable, а затем выполнять свои действия в обычном цикле for-each. Таким образом, вам не нужно обрабатывать исключения внутри лямбды.

try (Stream<Path> pathStream = Files.walk(Paths.get(path))
        .filter(Files::isRegularFile)) {

    for (Path file : (Iterable<Path>) pathStream::iterator) {
        // something that throws IOException
        Files.copy(file, System.out);
    }
}

Нашел этот трюк здесь: https://stackoverflow.com/a/32668807/1207791

person cfstras    schedule 17.12.2019

По-другому можно поступить, даже если кто-то уже предоставил прогулку по Java 8.

Это рекурсивно предоставит вам все файлы

  private Stream<File> files(File file) {
    return file.isDirectory()
            ? Arrays.stream(file.listFiles()).flatMap(this::files)
            : Stream.of(file);
}
person Michael    schedule 28.01.2020

public static String getExten(String path) {
    int i = path.lastIndexOf('.');
    if (i > 0) {
       return path.substring(i);
    }
    else return "";
}
public static List<String> GetAllFiles(String path, List<String>fileList){
    File file = new File(path);
    
    File[] files = file.listFiles();
    for(File folder:files) {
        if(extensions.contains(getExten(folder.getPath()))) {
            fileList.add(folder.getPath());
        }
    }
    File[] direcs = file.listFiles(File::isDirectory);
    for(File dir:direcs) {
        GetAllFiles(dir.getPath(),fileList);
    }
    return fileList;
    
}

Это простая рекурсивная функция, которая должна предоставить вам все файлы. extension - это список строк, который содержит только те расширения, которые принимаются. Примеры расширений = [.txt, .docx] и т. Д.

person Parikshit Phukan    schedule 17.08.2020

Пример выводит файлы * .csv в подкаталогах с рекурсивным поиском каталогов с помощью Files.find () из java.nio:

String path = "C:/Daten/ibiss/ferret/";
    logger.debug("Path:" + path);
    try (Stream<Path> fileList = Files.find(Paths.get(path), Integer.MAX_VALUE,
            (filePath, fileAttr) -> fileAttr.isRegularFile() && filePath.toString().endsWith("csv"))) {
        List<String> someThingNew = fileList.sorted().map(String::valueOf).collect(Collectors.toList());
        for (String t : someThingNew) {
            t.toString();
            logger.debug("Filename:" + t);
        }

    }

Публикуя этот пример, у меня возникли проблемы с пониманием того, как передать параметр имени файла в примере № 1, приведенном Брайаном, используя foreach в Stream-result -

Надеюсь это поможет.

person Ralf R.    schedule 12.10.2017

на основе ответа @Michael добавьте проверку, возвращает ли listFiles значение null

static Stream<File> files(File file) {
    return file.isDirectory()
            ? Optional.ofNullable(file.listFiles()).map(Stream::of).orElseGet(Stream::empty).flatMap(MainActivity::files)
            : Stream.of(file);
}

или используйте Lightweight-Stream-API, который поддерживает Android5 и Android6.

static Stream<File> files(File f) {
    return f.isDirectory() ? Stream.ofNullable(f.listFiles()).flatMap(MainActivity::files) : Stream.of(f);
}
person Yessy    schedule 12.10.2020

На основании ответа укладчика. Вот решение, работающее в JSP без каких-либо внешних библиотек, поэтому вы можете разместить его практически в любом месте на своем сервере:

<!DOCTYPE html>
<%@ page session="false" %>
<%@ page import="java.util.*" %>
<%@ page import="java.io.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>

<%!
    public List<String> files = new ArrayList<String>();
    /**
        Fills files array with all sub-files.
    */
    public void walk( File root ) {
        File[] list = root.listFiles();

        if (list == null) return;

        for ( File f : list ) {
            if ( f.isDirectory() ) {
                walk( f );
            }
            else {
                files.add(f.getAbsolutePath());
            }
        }
    }
%>
<%
    files.clear();
    File jsp = new File(request.getRealPath(request.getServletPath()));
    File dir = jsp.getParentFile();
    walk(dir);
    String prefixPath = dir.getAbsolutePath() + "/";
%>

Затем вы просто делаете что-то вроде:

    <ul>
        <% for (String file : files) { %>
            <% if (file.matches(".+\\.(apk|ipa|mobileprovision)")) { %>
                <li><%=file.replace(prefixPath, "")%></li>
            <% } %>
        <% } %>
    </ul>
person Nux    schedule 21.01.2014
comment
Хотя это, вероятно, работает, вопрос заключается в просмотре файлов, а не в отображении просматриваемых файлов. Лучше представьте свой алгоритм как таковой, не рекомендуется встраивать бизнес-логику в JSP. - person Samuel Kerrien; 15.06.2015
comment
Это зависит от того, что вы делаете. В корпоративном приложении вы абсолютно правы. Если вам это нужно просто как дополнение к простому автономному списку, тогда это прекрасно. - person Nux; 24.06.2015