Java, elenca solo le sottodirectory da una directory, non i file


100

In Java, come si elencano solo le sottodirectory di una directory?

Vorrei utilizzare la funzionalità java.io.File, qual è il metodo migliore in Java per farlo?

Risposte:


141

È possibile utilizzare la classe File per elencare le directory.

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

Aggiornare

Il commento dell'autore su questo post voleva un modo più veloce, ottima discussione qui: come recuperare un elenco di directory RAPIDAMENTE in Java?

Fondamentalmente:

  1. Se controlli la struttura del file, cercherò di evitare di entrare in quella situazione.
  2. In Java NIO.2, è possibile utilizzare la funzione directory per restituire un iteratore per consentire una maggiore scalabilità. La classe del flusso di directory è un oggetto che è possibile utilizzare per scorrere le voci in una directory.

ciao, grazie per la risposta. Ma non devo scorrere tutti gli elementi in una directory. Devo elencare direttamente la sottodirectory dalla directory. B'coz ho molti file e solo poche sottodirectory in una directory, quindi controllare isDirectory () richiede molto tempo. per favore rispondimi in un altro modo.
Lokesh Paunikar

Ho aggiornato il mio post, in particolare, dai un'occhiata al commento di Jon Skeet sulla domanda. E la risposta NIO da Java NIO 2 ha un iteratore per la funzione directory che restituisce un flusso di directory.
Mohamed Mansour

A quale commento di Skeet ti riferisci? Qual è la risposta più performante qui?
Stealth Rabbi

107

Una soluzione Java 8 molto semplice:

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

È equivalente all'utilizzo di un FileFilter (funziona anche con Java meno recenti):

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

4
Come funziona il doppio colon ::in questo caso?
snickers10m

Ho notato che nessun'altra risposta utilizza FileFilter, quindi ho aggiunto la versione equivalente senza utilizzare i riferimenti al metodo. Per ulteriori informazioni sui riferimenti ai metodi, fare riferimento a questa domanda SO o a questo articolo .
headsvk

questo ottiene sottodirectory o solo le directory direttamente sotto / tuo / percorso /?
amadain


14

@ Mohamed Mansour eri quasi arrivato ... l'argomento "dir" che stavi usando è in realtà il percorso attuale, quindi restituirà sempre true. Per vedere se il bambino è una sottodirectory o meno, è necessario testarlo.

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

Se sei interessato a una soluzione che utilizza Java 7 e NIO.2, potrebbe funzionare così:

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

Ciao e benvenuto in StackOverflow! Puoi approfondire un po 'la tua risposta? Come spiegare parti interessanti dei tuoi frammenti di codice o collegarti alla documentazione per ulteriori letture?
Richard-Degenne

Questa dovrebbe essere la risposta corretta in quanto fornisce un oggetto File con il percorso canonico completo. Potrebbe essere vecchio ma vale la pena sottolinearlo
Jero Dungog,

2

Per coloro che sono interessati anche a Java 7 e NIO, c'è una soluzione alternativa alla risposta di @ voo sopra . Possiamo usare un try-with-resources che chiama Files.find()e una funzione lambda che viene utilizzata per filtrare le directory.

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

Possiamo anche filtrare le directory per nome modificando la funzione lambda:

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

o per data:

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

Vorrei utilizzare la funzionalità java.io.File,

Nel 2012 (data della domanda) sì, non oggi. java.nioL'API deve essere favorita per tali requisiti.

Terribile con così tante risposte, ma non è il modo semplice in cui lo userei Files.walk().filter().collect().

A livello globale sono possibili due approcci:

1) Files.walk(Path start, )non ha maxDepthlimitazioni mentre

2) Files.walk(Path start, int maxDepth, FileVisitOption... options)permette di impostarlo.

Senza specificare alcuna limitazione di profondità, darebbe:

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

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

E se per motivi legacy, hai bisogno di ottenere un elenco di Filete puoi semplicemente aggiungere map(Path::toFile)un'operazione prima della raccolta:

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
}

C'è anche Files.list(Path)che probabilmente è lo stesso di Files.walk(Path,1).
David L.

@David L In effetti Files.list(Path)è una giusta alternativa se non vogliamo iterare in modo ricorsivo le cartelle. Per scorrere le cartelle in modo ricorsivo, si walk()adatta meglio.
davidxxx


0

Data una directory di partenza come file String

  1. Crea un metodo che prenda un Stringpercorso come parametro. Nel metodo:
  2. Crea un nuovo oggetto File basato sulla directory iniziale
  3. Ottieni un array di file nella directory corrente utilizzando il listFilesmetodo
  4. Esegui il ciclo sull'array di file
    1. Se è un file, continua a eseguire il loop
    2. Se è una directory, stampare il nome e ricorrere a questo nuovo percorso di directory

ciao, grazie per la risposta. Ma non devo scorrere tutti gli elementi in una directory. Devo elencare direttamente la sottodirectory dalla directory. B'coz ho molti file e solo poche sottodirectory in una directory, quindi controllare isDirectory () richiede molto tempo. per favore rispondimi in un altro modo.
Lokesh Paunikar

0

Ecco la soluzione per il mio codice. Ho appena fatto un piccolo cambiamento dalla prima risposta . Questo elencherà tutte le cartelle solo nella directory desiderata riga per riga:

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!");
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.