Java, wyświetla tylko podkatalogi z katalogu, a nie pliki


100

W Javie, jak wyświetlić tylko podkatalogi z katalogu?

Chciałbym skorzystać z funkcjonalności java.io.File. Jaka jest najlepsza metoda w Javie, aby to zrobić?

Odpowiedzi:


141

Możesz użyć klasy File, aby wyświetlić listę katalogów.

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));

Aktualizacja

Komentarz autora do tego postu chciał szybszego sposobu, świetna dyskusja tutaj: Jak szybko pobrać listę katalogów w Javie?

Gruntownie:

  1. Jeśli kontrolujesz strukturę plików, starałbym się uniknąć takiej sytuacji.
  2. W Javie NIO.2 można użyć funkcji katalogów, aby zwrócić iterator, aby umożliwić większe skalowanie. Klasa strumienia katalogu to obiekt, którego można używać do iteracji po wpisach w katalogu.

cześć, dziękuję za odpowiedź. Ale nie muszę iterować po wszystkich elementach w katalogu. Muszę bezpośrednio wyświetlić podkatalog z katalogu. B'coz Mam dużo plików i tylko kilka podkatalogów w katalogu, więc sprawdzenie isDirectory () jest czasochłonne. proszę, odpowiedz mi w inny sposób.
Lokesh Paunikar

Zaktualizowałem swój post, w szczególności spójrz na komentarz Jona Skeeta do pytania. A odpowiedź NIO, ponieważ Java NIO 2 ma iterator dla funkcji katalogów, która zwraca strumień katalogów.
Mohamed Mansour,

Jaki komentarz Skeet masz na myśli? Jaka jest tutaj lepsza odpowiedź?
Stealth Rabbi

107

Bardzo proste rozwiązanie Java 8:

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

Jest to równoważne użyciu FileFilter (działa również ze starszą Javą):

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

4
Jak działa podwójny dwukropek ::w tym przypadku?
snickers 10 min

Zauważyłem, że żadna inna odpowiedź nie używa FileFilter, więc dodałem równoważną wersję bez użycia odwołań do metod. Więcej informacji na temat odwołań do metod można znaleźć w tym pytaniu SO lub w tym artykule .
Headsvk

czy to pobiera podkatalogi czy tylko katalogi bezpośrednio w / twoja / ścieżka /?
amadain

@amadain bez rekursji zgodnie z oczekiwaniami docs.oracle.com/javase/7/docs/api/java/io/File.html#listFiles ()
headsvk

14

@Mohamed Mansour, prawie byłeś ... argument "dir", którego używałeś, jest w rzeczywistości aktualną ścieżką, więc zawsze zwróci prawdę. Aby sprawdzić, czy dziecko jest podkatalogiem, czy nie, musisz je przetestować.

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

Jeśli jesteś zainteresowany rozwiązaniem wykorzystującym Javę 7 i NIO.2, może to wyglądać tak:

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)
    )
);

Cześć i witaj w StackOverflow! Czy możesz trochę rozwinąć swoją odpowiedź? Lubisz wyjaśniać interesujące części fragmentów kodu lub linkować do dokumentacji w celu dalszego czytania?
Richard-Degenne

Powinna to być poprawna odpowiedź, ponieważ zapewnia obiektowi File z pełną ścieżką kanoniczną. To może być stare, ale warto na to zwrócić uwagę
Jero Dungog

2

Dla tych, którzy są również zainteresowani Javą 7 i NIO, istnieje alternatywne rozwiązanie powyższej odpowiedzi @ voo . Możemy użyć wywołania try-with-resourcesFiles.find() i funkcji lambda, która jest używana do filtrowania katalogów.

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) {
    ...
}

Możemy nawet filtrować katalogi według nazwy, zmieniając funkcję lambda:

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

lub według daty:

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

Chciałbym skorzystać z funkcjonalności java.io.File,

W 2012 roku (data zapytania) tak, nie dzisiaj. java.nioW przypadku takich wymagań należy preferować API.

Okropne z tak wieloma odpowiedziami, ale nie w prosty sposób, w jaki bym tego użył Files.walk().filter().collect().

Globalnie możliwe są dwa podejścia:

1) Files.walk(Path start, )nie ma żadnych maxDepthograniczeń

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)pozwala to ustawić.

Bez określenia ograniczeń głębokości dałoby:

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

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

A jeśli z powodów przestarzałych potrzebujesz uzyskać Listę File, możesz po prostu dodać map(Path::toFile)operację przed kolekcją:

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
}

Jest też Files.list(Path)prawdopodobnie to samo co Files.walk(Path,1).
David L.

@David L Rzeczywiście Files.list(Path)jest uczciwą alternatywą, jeśli nie chcemy iterować rekurencyjnie folderów. Aby iterować foldery rekurencyjnie, walk()lepiej pasuje.
davidxxx


0

Biorąc pod uwagę katalog początkowy jako plik String

  1. Utwórz metodę, która przyjmuje Stringścieżkę jako parametr. W metodzie:
  2. Utwórz nowy obiekt File na podstawie katalogu startowego
  3. Pobierz tablicę plików w bieżącym katalogu przy użyciu listFilesmetody
  4. Zapętlaj tablicę plików
    1. Jeśli to plik, kontynuuj zapętlanie
    2. Jeśli jest to katalog, wydrukuj nazwę i powtórz w tej nowej ścieżce katalogu

cześć, dziękuję za odpowiedź. Ale nie muszę iterować po wszystkich elementach w katalogu. Muszę bezpośrednio wyświetlić podkatalog z katalogu. B'coz Mam dużo plików i tylko kilka podkatalogów w katalogu, więc sprawdzenie isDirectory () jest czasochłonne. proszę, odpowiedz mi w inny sposób.
Lokesh Paunikar

0

Oto rozwiązanie dla mojego kodu. Zrobiłem tylko małą zmianę od pierwszej odpowiedzi . Spowoduje to wyświetlenie wszystkich folderów tylko w wybranym katalogu wiersz po wierszu:

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!");
        }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.