Java, список лише підкаталогів з каталогу, а не файлів


100

Як у Java я перелічу лише підкаталоги з каталогу?

Я хотів би скористатися функцією java.io.File, який найкращий метод у Java для цього?

Відповіді:


141

Клас Файл можна використовувати для списку каталогів.

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));

Оновлення

Коментар автора до цього допису хотів швидшого шляху, великого обговорення тут: Як швидко отримати список каталогів на Яві?

В основному:

  1. Якщо ви керуєте структурою файлів, я б намагався не потрапляти в цю ситуацію.
  2. У Java NIO.2 ви можете використовувати функцію каталогів, щоб повернути ітератор, щоб забезпечити більш масштабне масштабування. Клас потокового каталогу - це об'єкт, який ви можете використовувати для повторення записів у каталозі.

привіт, дякую за відповідь. Але мені не доведеться повторювати всі елементи в каталозі. Я маю безпосередньо перелічити підкаталог із каталогу. B'coz У мене багато файлів і лише кілька підкаталогів у каталозі, тому перевірка isDirectory () займає багато часу. будь ласка, відповідайте мені іншим способом.
Локеш Паунікар

Я оновив свій пост, зокрема, погляньте на коментар Джона Скіта до цього питання. І відповідь NIO, оскільки Java NIO 2 має ітератор функції каталогів, який повертає потік каталогів.
Мохамед Мансур

Який коментар Скіта ви маєте на увазі? Яка відповідь тут найкраще?
Стелс-рабин

107

Дуже просте рішення Java 8:

File[] directories = new File("/your/path/").listFiles(File::isDirectory);

Це еквівалентно використанню FileFilter (працює і зі старшою Java):

File[] directories = new File("/your/path/").listFiles(new FileFilter() {
    @Override
    public boolean accept(File file) {
        return file.isDirectory();
    }
});

4
Як працює подвійна двокрапка ::в цьому випадку?
snickers10m

Я помітив, що жодна інша відповідь не використовує FileFilter, тому я додав еквівалентну версію без використання посилань на методи. Докладніше про посилання на методи див. У цьому питанні щодо цієї проблеми чи в цій статті .
headvk

чи отримує це підкаталоги або просто каталоги безпосередньо під / your / path /?
amadain

@amadain немає рекурсії, як очікувалося, docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
headsvk

14

@Mohamed Mansour, ти майже був там ... аргумент "dir", який ти використовував, - це насправді шлях вилікування, тому він завжди повернеться правдою. Для того, щоб переконатися, що дитина є підкаталогом чи ні, вам потрібно перевірити цю дитину.

File file = new File("/path/to/directory");
String[] directories = file.list(new FilenameFilter() {
  @Override
  public boolean accept(File current, String name) {
    return new File(current, name).isDirectory();
  }
});
System.out.println(Arrays.toString(directories));

7

Якщо ви зацікавлені в рішенні, що використовує Java 7 і NIO.2, воно може вийти так:

private static class DirectoriesFilter implements Filter<Path> {
    @Override
    public boolean accept(Path entry) throws IOException {
        return Files.isDirectory(entry);
    }
}

try (DirectoryStream<Path> ds = Files.newDirectoryStream(FileSystems.getDefault().getPath(root), new DirectoriesFilter())) {
        for (Path p : ds) {
            System.out.println(p.getFileName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

3
ArrayList<File> directories = new ArrayList<File>(
    Arrays.asList(
        new File("your/path/").listFiles(File::isDirectory)
    )
);

Привіт, і ласкаво просимо до StackOverflow! Чи можете ви трохи розібратися у своїй відповіді? Як пояснення цікавих частин фрагментів коду або посилання на документацію для подальшого читання?
Річард-Дегенна

Це має бути правильною відповіддю, оскільки він надає об’єкту File повний канонічний шлях. Це може бути старим, але на це варто вказати
Джеро Дангог,

2

Для тих, хто також цікавиться Java 7 та NIO, є альтернативне рішення відповіді @ voo вище . Ми можемо використовувати пробні ресурси, що викликають, Files.find()та лямбда-функцію, яка використовується для фільтрації каталогів.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;


final Path directory = Paths.get("/path/to/folder");

try (Stream<Path> paths = Files.find(directory, Integer.MAX_VALUE, (path, attributes) -> attributes.isDirectory())) {
    paths.forEach(System.out::println);
} catch (IOException e) {
    ...
}

Ми навіть можемо фільтрувати каталоги за назвою, змінюючи функцію лямбда:

(path, attributes) -> attributes.isDirectory() && path.toString().contains("test")

або за датою:

final long now = System.currentTimeMillis();
final long yesterday = new Date(now - 24 * 60 * 60 * 1000L).getTime();

// modified in the last 24 hours
(path, attributes) -> attributes.isDirectory() && attributes.lastModifiedTime().toMillis() > yesterday

2

Я хотів би використовувати функцію java.io.File,

У 2012 році (дата запитання) так, не сьогодні. java.nioТакі вимоги повинні надавати перевагу API.

Жахливо з такою кількістю відповідей, але не з простих способів, якими я б користувався Files.walk().filter().collect().

В усьому світі можливі два підходи:

1) Files.walk(Path start, )поки не має maxDepthобмежень

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)дозволяє встановити його.

Не вказуючи жодних обмежень глибини, це дасть:

Path directory = Paths.get("/foo/bar");

try {
    List<Path> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

І якщо з застарілих причин вам потрібно отримати Список, Fileви можете просто додати map(Path::toFile)операцію перед збором:

Path directory = Paths.get("/foo/bar");

try {
    List<File> directories =
            Files.walk(directory)
                 .filter(Files::isDirectory)
                 .map(Path::toFile)
                 .collect(Collectors.toList());
} catch (IOException e) {
    // process exception
}

Є й те, Files.list(Path)що, ймовірно, те саме, що Files.walk(Path,1).
Девід Л.

@David L Дійсно Files.list(Path), це справедлива альтернатива, якщо ми не хочемо повторювати рекурсивні папки. Ітератизувати папки рекурсивно, walk()краще підходить.
davidxxx

1

Рішення, яке працювало на мене, відсутнє у списку відповідей. Тому я публікую це рішення тут:

File[]dirs = new File("/mypath/mydir/").listFiles((FileFilter)FileFilterUtils.directoryFileFilter());

Тут я використав org.apache.commons.io.filefilter.FileFilterUtilsз Apache commons-io-2.2.jar. Його документація доступна тут: https://commons.apache.org/proper/commons-io/javadocs/api-2.2/org/apache/commons/io/filefilter/FileFilterUtils.html


0

Дано початковий каталог як String

  1. Створіть метод, який приймає Stringшлях як параметр. У способі:
  2. Створіть новий об'єкт File на основі пускової директорії
  3. Отримайте масив файлів у поточному каталозі, використовуючи listFilesметод
  4. Переведіть петлю на масив файлів
    1. Якщо це файл, продовжуйте циклічно
    2. Якщо це каталог, роздрукуйте ім'я та повторіть цей новий шлях до каталогу

привіт, дякую за відповідь. Але мені не доведеться повторювати всі елементи в каталозі. Я маю безпосередньо перелічити підкаталог із каталогу. B'coz У мене багато файлів і лише кілька підкаталогів у каталозі, тому перевірка isDirectory () займає багато часу. будь ласка, відповідайте мені іншим способом.
Локеш Паунікар

0

Ось рішення для мого коду. Я щойно змінив літле з першої відповіді . У цьому списку будуть вказані всі папки лише в потрібному каталозі по рядку:

try {
            File file = new File("D:\\admir\\MyBookLibrary");
            String[] directories = file.list(new FilenameFilter() {
              @Override
              public boolean accept(File current, String name) {
                return new File(current, name).isDirectory();
              }
            });
            for(int i = 0;i < directories.length;i++) {
                if(directories[i] != null) {
                    System.out.println(Arrays.asList(directories[i]));

                }
            }
        }catch(Exception e) {
            System.err.println("Error!");
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.