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.