2015-04-11 3 views
15

Ich habe folgende Verzeichnisstrukturen:Wie verwendet man Files.walk() ... um ein Diagramm von Dateien basierend auf Bedingungen zu erhalten?

/path/to/stuff/org/foo/bar/ 
/path/to/stuff/org/foo/bar/1.2.3/ 
/path/to/stuff/org/foo/bar/1.2.3/myfile.ext 
/path/to/stuff/org/foo/bar/1.2.4/ 
/path/to/stuff/org/foo/bar/1.2.4/myfile.ext 
/path/to/stuff/org/foo/bar/blah/ 
/path/to/stuff/org/foo/bar/blah/2.1/ 
/path/to/stuff/org/foo/bar/blah/2.1/myfile.ext 
/path/to/stuff/org/foo/bar/blah/2.2/ 
/path/to/stuff/org/foo/bar/blah/2.2/myfile.ext 

Ich mag würde die folgende Ausgabe erhalten:

/path/to/stuff/org/foo/bar/ 
/path/to/stuff/org/foo/bar/blah/ 

Ich habe den folgenden Code (siehe unten), was ineffizient ist, wie es aus druckt:

/path/to/stuff/org/foo/bar/ 
/path/to/stuff/org/foo/bar/ 
/path/to/stuff/org/foo/bar/blah/ 
/path/to/stuff/org/foo/bar/blah/ 

Hier ist die Java-Code:

public class LocatorTest 
{ 

    @Test 
    public void testLocateDirectories() 
      throws IOException 
    { 
     long startTime = System.currentTimeMillis(); 

     Files.walk(Paths.get("/path/to/stuff/")) 
      .filter(Files::isDirectory) 
      .forEach(Foo::printIfArtifactVersionDirectory); 

     long endTime = System.currentTimeMillis(); 

     System.out.println("Executed in " + (endTime - startTime) + " ms."); 
    } 

    static class Foo 
    { 

     static void printIfArtifactVersionDirectory(Path path) 
     { 
      File f = path.toAbsolutePath().toFile(); 
      List<String> filePaths = Arrays.asList(f.list(new MyExtFilenameFilter())); 

      if (!filePaths.isEmpty()) 
      { 
       System.out.println(path.getParent()); 
      } 
     } 

    } 

} 

Der Filter:

public class MyExtFilenameFilter 
     implements FilenameFilter 
{ 

    @Override 
    public boolean accept(File dir, String name) 
    { 
     return name.endsWith(".ext"); 
    } 

} 
+1

'.allMatch()' kompiliert nicht. – Seelenvirtuose

+1

@Seelenvirtuose: Entschuldigung. Behoben. – carlspring

Antwort

20
Files.walk(Paths.get("/path/to/stuff/")) 
    .filter(p -> p.toString().endsWith(".ext")) 
    .map(p -> p.getParent().getParent()) 
    .distinct() 
    .forEach(System.out::println); 

Dieser filtert alle Dateien, die die Erweiterung und erhält den übergeordneten Pfad ihrer Verzeichnis haben. distinct stellt sicher, dass jeder Pfad nur einmal verwendet wird.

+0

Ich würde empfehlen, diese Antwort zu akzeptieren, da sie recht elegant ist und die Java 8-Funktionen nutzt. –

+1

Warum nicht '.filter (p -> pendsWith (". Ext "))'? – user2336315

+3

@ user2336315 Da es den Dateiteil nicht berücksichtigt, nur den Verzeichnisteil eines Pfades. – zeroflagL

3

Sie die Methode printIfArtifactVersionDirectory für alle besuchten Verzeichnisse aufrufen. Ich habe ein wenig ändern es offensichtlich zu machen:

static void printIfArtifactVersionDirectory(Path path) { 
    System.out.println("--- " + path); 
    ... 
} 

Mit dieser zusätzlichen Ausgabe erhalten Sie:

--- C: \ Projects \ Sachen
--- C: \ Projects \ \ Sachen org
--- C: \ Projects \ Sachen \ org \ foo
--- C: \ Projects \ Sachen \ org \ foo \ bar
--- C: \ Projects \ Sachen \ org \ foo \ bar \ 1.2.3
C: \ Projekte \ stuff \ org \ foo \ bar
--- C: \ Projekte \ stuff \ org \ foo \ bar \ 1.2.4
C: \ Projekte \ stuff \ org \ foo \ bar
--- C: \ Projekte \ stuff \ org \ foo \ blah bar \
--- C: \ Projects \ Sachen \ org \ foo \ bar \ bla \ 2.1
C: \ Projects \ Sachen \ org \ foo \ bar \ blah
--- C: \ Projects \ Sachen \ org \ \ blah foo \ bar \ 2.2
C: \ Projects \ Sachen \ org \ foo \ bar \ blah

so erhalten Sie die Ausgabe so oft Sie Artefakt Version Verzeichnisse haben. Wenn Sie merken möchten, dass Sie bereits die Ausgabe für ein Verzeichnis vorgenommen haben, müssen Sie diese Informationen irgendwo speichern.Eine schnelle Implementierung könnte sein:

static class Foo { 
    private static final Set<Path> visited = new HashSet<>(); 

    static void printIfArtifactVersionDirectory(Path path) { 
     ... 
     Path parent = path.getParent(); 
     if (!filePaths.isEmpty() && !visited.contains(parent)) { 
      visited.add(parent); 
      System.out.println(parent); 
     } 
    } 
} 

Mit diesem erhalten Sie die erwartete Ausgabe:

C: \ Projects \ Sachen \ org \ foo \ bar
C: \ Projects \ Sachen \ org \ foo \ bar \ blah

Eine bessere Lösung wäre es, den Satz zu verwenden, um die besuchten Eltern zu speichern und sie nur drucken nach besuchen sie alle:

static class PathStore { 
    private final Set<Path> store = new HashSet<>(); 

    void visit(Path path) { 
     File f = path.toAbsolutePath().toFile(); 
     List<String> filePaths = Arrays.asList(f.list(new MyExtFilenameFilter())); 
     if (!filePaths.isEmpty()) { 
      store.add(path.getParent()); 
     } 
    } 

    void print() { 
     store.forEach(System.out::println); 
    } 
} 

Verbrauch:

PathStore pathStore = new PathStore(); 
Files.walk(Paths.get("/path/to/stuff/")) 
     .filter(Files::isDirectory) 
     .forEach(pathStore::visit); 
pathStore.print(); 
+0

Hallo, danke für diese Antwort! Ihre Antwort ist mehr als ausgezeichnet und ich werde es in einem der Fälle (in dem es Follow-up-Aktionen gibt) so verwenden. Ich werde jedoch den anderen wählen, weil es die meiste Zeit so verwendet wird, da es viel einfacher und eleganter ist. Vielen Dank aber! – carlspring

Verwandte Themen