2009-05-23 8 views
17

Ich möchte eine Liste von alle Dateien in einem Verzeichnis sammeln, insbesondere einschließlich Unterverzeichnissen. Ich mag es nicht, Dinge selbst zu machen, also verwende ich FileUtils.listFiles von Apache Commons IO. So habe ich so etwas wie:Nur Verzeichnisse rekursiv finden mit FileUtils.listFiles

import java.io.File; 
import java.util.Collection; 

import org.apache.commons.io.FileUtils; 
import org.apache.commons.io.filefilter.TrueFileFilter; 

public class TestListFiles { 
    public static void main(String[] args) { 
    Collection<File> found = FileUtils.listFiles(new File("foo"), 
     TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE); 
    for (File f : found) { 
     System.out.println("Found file: " + f); 
    } 
    } 
} 

Problem ist, scheint dies nur normale Dateien, keine Verzeichnisse zu finden:

$ mkdir -p foo/bar/baz; touch foo/one_file 
$ java -classpath commons-io-1.4.jar:. TestListFiles 
Found file: foo/one_file 

ich bereits TrueFileFilter sowohl der Filter durchströmt, so kann ich‘ Ich denke an etwas umfassenderes. Ich möchte es auflisten: "foo", "foo/one_file", "foo/bar", "foo/bar/baz" (in beliebiger Reihenfolge).

Ich würde auch nicht FileUtils Lösungen akzeptieren, aber es scheint albern zu sein, um mein eigenes BFS zu schreiben, oder sogar die Menge der übergeordneten Verzeichnisse aus der Liste zu sammeln, die ich bekomme. (Das würde sowieso leere Unterverzeichnisse vermissen.) Dies ist unter Linux, FWIW.

Antwort

0

Es sollte funktionieren, basierend auf ihrer API.

Hier ist meine eigene Version von FileUtils, nicht so vollständig wie Commons IO, es enthält nur, was ich brauche. Suchen Sie nach findFiles oder verwenden Sie iterieren Sie, um zu vermeiden, riesige Listen zu erstellen (irgendwann/die meiste Zeit Sie wollen nur etwas mit diesen Dateien tun, so dass sie in einer Liste sammeln macht keinen Sinn).

6

Wenn Sie sich die source code ansehen und zwischen den Zeilen im JavaDoc lesen, werden Sie feststellen, dass diese API leider nicht dafür ausgelegt ist, das zu tun, was Sie wollen. Es wird eine Liste von Dateien (keine Liste der Dateien und Verzeichnisse) zurückgeben, die den bereitgestellten Argumenten entsprechen. Im Quellcode - sehen Sie sich die Methode innerListFiles an - werden Sie sehen, dass die Verzeichnisse durchsucht werden und nicht zur Ergebnisliste hinzugefügt wird.

Mir ist keine öffentliche API bekannt, die das macht, was Sie wollen. Hoffentlich wird jemand anderes von einem wissen. Die meisten werden wahrscheinlich ein DFS, kein BFS sein, was für Ihre Zwecke von Bedeutung sein kann. (Bisher alle Java-Code, den ich je gesehen habe, hat eine Verzeichnisbaum-Traversal es über eine Tiefensuche gemacht. Was nicht heißt, dass BFS's natürlich nicht da draußen sind.)

Wenn Sie wirklich eine Liste von alles in einem bestimmten Verzeichnis wollen, ist es einfach genug, um Ihre eigenen zu rollen. Aber ich verstehe deinen Wunsch, das Rad nicht neu zu erfinden.

Hinweis: Es ist möglich, dass Apache Commons Finder unterstützt, was Sie brauchen, aber diese Bibliothek ist in der Commons Sandbox, was bedeutet, dass es in diesem Stadium experimenteller ist. Es kann oder kann nicht vollständig sein und es kann oder kann nicht beibehalten werden. Es kann auch Schwergewicht sein für das, was Sie suchen.

+0

Dank für den Zeiger - ich kann am Ende nur das kopieren und es funktioniert. Ich nehme an, das ist, was ich bekomme, wenn man annimmt, dass alles, was eine Datei unter Linux ist (Verzeichnisse, Links, Pipes, Geräte), eine Datei nach Commons Definition ist. –

+5

Ich hätte die gleiche Annahme gemacht, dass du es getan hast - bis es nicht funktioniert hat. Sie sollten ihr JavaDoc wirklich deutlicher machen, um es klar zu machen. – Eddie

+0

Wow, danke für den Zeiger. Es gibt keinen Hinweis in der Javadoc, dass Verzeichnisse ausgeschlossen sind. Ich weiß nicht wer auf der Erde davon ausgeht, dass Verzeichnisse keine Dateien sind! – WhyNotHugo

6

Ich vermeide die Java IO-Bibliotheken in den meisten meiner nicht-trivialen Anwendungen und bevorzuge stattdessen Commons VFS. Ich glaube, ein Anruf an this method mit den entsprechenden Parametern wird Ihr Ziel erreichen, aber ich werde es einen langen Weg geben, um für die Funktionalität zu gehen.

Konkret wird dieser Code tun, was Sie wollen:

FileObject[] files = fileObject.findFiles(new FileSelector() { 
     public boolean includeFile(FileSelectInfo fileInfo) { 
      return fileInfo.getFile().getType() == FileType.FOLDER; } 

     public boolean traverseDescendents(FileSelectInfo fileInfo) { 
      return true; 
     } 
    }); 

wo Fileobject eine Instanz von Fileobject ist.

+0

"Diese Methode" ist ein fehlerhafter Link. –

+0

Wir können es reparieren :-) – Ben

1

Eine einfachere + Komplett Commons VFS Lösung:

FileSystemManager fsManager = VFS.getManager(); 
FileObject fileObject = fsManager.resolveFile("yourFileNameHere"); 
FileObject[] files = fileObject.findFiles(new FileTypeSelector(FileType.FOLDER)) 
6

Haben Sie versucht einfach:

File rootFolder = new File(...); 
File[] folders = rootFolder.listFiles((FileFilter) FileFilterUtils.directoryFileFilter()); 

Es scheint für mich zu arbeiten. Sie werden natürlich Rekursion benötigen.

Ich hoffe, es hilft.

+0

Danke, das funktioniert am besten für mich. Ich möchte keine weitere Bibliothek für VFS hinzufügen. –

+0

Das Problem ist, dass Java io schrecklich langsam ist. – Kieveli

19

Eine alte Antwort, aber das funktioniert für mich:

FileUtils.listFilesAndDirs(new File(dir), TrueFileFilter.INSTANCE, DirectoryFileFilter.DIRECTORY); 

zeigt beides:

Ich benutze:

FileUtils.listFilesAndDirs(new File(dir), new NotFileFilter(TrueFileFilter.INSTANCE), DirectoryFileFilter.DIRECTORY) 

Nur zeigt Verzeichnisse und Dateien nicht ...

+0

Das war viel langsamer für mich als Benutzer573041 die Antwort auf den Punkt, den ich meine App getötet habe. –

+0

Ein Ersatz für "neue NotFileFilter (TrueFileFilter.INSTANCE)" ist nur "FalseFileFilter.INSTANCE". Ich denke, Ihre Antwort mit "FileUtils.listFilesAndDirs (...)" passt am besten, eine einfache Lösung, nach der das OP fragt. –

+0

Ich benutze Sammlung c = FileUtils.listFilesAndDirs (neue Datei ("Ziel"), FalseFileFilter.INSTANCE, TrueFileFilter.INSTANCE); –

Verwandte Themen