Komplette Verzeichnisstruktur auslesen mit newDirectoryStream

Guten Tag zusammen,

ich versuche mich gerade an dieser Aufgabe: Java-Aufgaben - Ein-/Ausgabe

Ich habe es bereits geschafft, die Verzeichnisse auszugeben und möchte nun noch die Unterverzeichnisse und Dateien ausgeben, wie in der Aufgabe gefordert. in C:// selbst lassen sich ja nur Ordne anlegen. Habt ihr Tipps, wie man das am schlausten coden könnte? Ich habe vor, für jeden Directory Eintrag (Verzeichnis) eine Schleife auszuführen und die Unterverzeichnisse und Dateien auszugeben. Wenn ich das ganze aber ausdenke, stoße ich auf Probleme, wenn es x Unterverzeichnisse gibt. Wie soll ich prüfen ob es vom Unterverzeichnis ein weiteres Unterverzeichnis und noch eins und so weiter gibt? Ziel ist es, alle Dateien und Verzeichnisse meines PC’s aufzulisten. Ich weiß nicht, ob das Ziel der Aufgabe ist, ich möchte es aber dennoch versuchen. Hier mal mei bisheriger Code:


	public static void main(String[] args) throws IOException {

		File file = new File("C://");
		Path dir = Paths.get(file.toURI());
		DirectoryStream<Path> dirsys = Files.newDirectoryStream(dir);

		for (Path t : dirsys) {

			System.out.println("[" + t + "]");
		}

	}
}```


Gruß

Stichwort: Rekursion!

Schreibe dir eine Methode die den Inhalt eines(!) Ordners ausgibt. Diese kannst du dann rekursiv für alle Unterverzeichnisse aufrufen.

Super Danke das Versuch ich gleich mal! Rekursion heißt ja nur, dass sich die Methode selbst aufruft, richtig? und noch was: kanns sein, dass hier alle aus dem Java forum sind? Warum sind denn die ganzen ehemaligen guten Helferlein dort gesperrt?

Gruß

Ja viele.

Aus Gründen :smiley: Ich denke es würde zu lange dauern das nochmal alles aufzurollen.

Oder nimm eine Datenstruktur.

Füge ein, wenn File-Array nicht null und aktuelles File ein Verzeichnis ist,
wiederhole mit dem als ersten Eingefügte.

OT: Es sind viele da, die viele Fragen beantwortet habn, aber leider sind wir nicht so gut frequentiert.

Weil Mitte 2013 das Forum vom Herrn Langwald urplötzlich übernommen wurde und seine Erwartungen und sein Verhalten nicht mit den Erwartungen vieler Leute die dafür verantwortlich sind, was den Ruf und die Qualität des Forums ausmachte, in Einklang zu bringen war.

Rekursion heißt das sich die Methode selbst aufruft!

in deiner Schleife mußt du also Prüfen, ob der Path eine Datei ist oder eine Ordner. Beim Ordner einfach die Methode mit diesem Ordner aufrufen.

[ot]

Aus Gründen :smiley: Ich denke es würde zu lange dauern das nochmal alles aufzurollen.[/QUOTE]

Und es würden zu viele schlimme Worte in der Erklärung vorkommen :smiley:
[/ot]

Ehrlich gesagt habe ich mit der neuen File-API selbst noch nicht viel gearbeitet, aber… es gibt auch eine Lösung, bei der man die Rekursion nicht selbst bauen muss: In Files#walkFileTree kann man einen visitor reinstopfen, der über jede besuchte Datei benachrichtigt wird:

package bytewelt;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

public class WalkFileTreeExample
{
    public static void main(String[] args) throws IOException
    {
        Path path = FileSystems.getDefault().getPath("C:/");
        FileVisitor<Path> visitor = new SimpleFileVisitor<Path>()
        {
            @Override
            public FileVisitResult visitFile(
                Path file, BasicFileAttributes attrs) 
            {
                System.out.println(file);
                return FileVisitResult.CONTINUE;
            };
            @Override
            public FileVisitResult visitFileFailed(
                Path file, IOException exp) 
            {
                return FileVisitResult.CONTINUE;
            }            
        };
        Files.walkFileTree(path, visitor);        
    }
}

(Das kann man ggf. noch anpassen, z.B. auf „Nur Verzeichnisse“, oder „Nur bis zu einer bestimmten Tiefe“ etc…)

Guten Abend zusammen, ich hoffe es ist noch jemand wach^^

Nach etwas Überlegung ist folgender Code zustande gekommen. Ich brauchte ein wenig, weil ich Rekursion vorher noch nie gemacht habe, aber seht selbst. Mal davon abgesehen, dass das alles etwas „quick and dirty“ ist, geht das glaub ich für’s erste klar.


	public void showDirectory(File root) throws IOException, AccessDeniedException {

		boolean isDirectory = root.isDirectory();

		if (root.exists()) { /* ------------------------------------------------------------------prüft, ob das File/Directory existiert*/

			if (isDirectory) { /* ----------------------------------------------------------------Ablauf, wenn root ein Directory ist*/

				try {
					Path path = Paths.get(root.toURI());                                        //Anlegen der Path-Variable, die der MAthode newDirectoryStream übergeben werden muss
					DirectoryStream<Path> dirlist = Files.newDirectoryStream(path);             // Erzeugen des DirectoryStream

					for (Path item : dirlist) {                                                  /* gibt alle Directorys aus, die root enthält*/

						System.out.println(item);/*---------------------------------------------- Druckt das vollständige Verzeichnis auf der Konsole*/
						showDirectory(item.toFile());/*                                          rekursiver Methodenaufruf, wenn root ein Verzeichnis ist. Führt dazu, dass bis ins letzte Unterverzeichnis vorgedrungen wird
						                                                                         danach Sprung zum nächsten Verzeichnis/Datei der ersten Wurzel, hier: C://*/
					}
				} catch (Exception e) {
					System.out.println("Kein Zugriff!");/*   -------------------------------------Exception in der Regel, wenn keine Leseerlaubnis vorliegt*/
					e.printStackTrace();
				}

			} else {/*---------------------------------------------------------------------------- Falls root eine Datei ist, wird diese auf de rKonsole mit zugehörigem Verzeichnis gedruckt*/
				System.out.println("Datei " + "[" + root.getName() + "]" + "befindet sich in Verzeichnis " + "["
						+ root.getParent() + "]");
			}
		}

		else {
			System.out.println("" + "Gesuchter Pfad existiert nicht!");/* -------------------------Sollte das übergebene File root nicht existieren, wird eine Fehlermeldung ausgegeben*/
		}

	}
}```


```public class DirectoryThread implements Runnable {

	DirectoryM dirM;
	public static void main(String[] args) {
		
		// Ausführen der Methode showDirectory() mit Hilfe eines Threads
		DirectoryThread dirThread = new DirectoryThread();
		Thread directoryThread = new Thread(dirThread);
		directoryThread.start();
		System.out.println("started");
		
	}

	@Override
	public void run() {
		System.out.println("reached run method");
		
		dirM = new DirectoryM();
				try {
					dirM.showDirectory(new File("C:\"));
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		
	}
}

Danke für eure Hilfsbereitschaft, Beispiel ist kompilierbar, falls jemand Interesse hat :slight_smile:

Kurzform: Ein hat das Forum aufgekauft und alles mit häßlicher, dämlicher Werbung zugeschissen. Als er von einigen langjährigen Usern höflich, dezent und formvollendet stilvoll darauf hingewiesen wurde, dass das nicht so stellar großartig ist, wurden diese einfach für immer gesperrt.

Trotzdem ist das kein Grund, wegen Herrn X eine öffentliche Hetzjagd zu veranstalten. Und genau das ist geschehen. Und zwar von allen. Ich denke nicht, dass Herr X eine Entschuldigung erwartet, sonder einfach nur in Ruhe gelassen werden will, und zwar von allen. Over and out

[ot]
Wie immer kompletter Blödsinn
[/ot]

Mit Java 8 geht Files.walkFileTree aus dem Beispiel von Marco13 wesentlich kürzer.

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class WalkDir {

    private static void walkDir(Path path) throws IOException {
      Files.walk(path)
         .map(WalkDir::formatPath)
         .forEach(System.out::println);
    }

    private static String formatPath(Path p) {
      if (Files.isDirectory(p)) {
         return String.format("Pfad gefunden %s", p);
      }
      else {
         return String.format("Datei %s befindet sich in Verzeichnis %s", p, p.getParent());
      }
    }

    public static void main(String[] args) throws IOException {
      Path path = ...;
      walkDir(path);
    }
}

@Unregistered: Unter Windows fliegt dann eine


Exception in thread "main" java.io.UncheckedIOException: java.nio.file.AccessDeniedException: C:\$Recycle.Bin\...

(Dafür mußte man im Ursprünglichen Beispiel auch “visitFileFailed” überschreiben - ansonsten hätte man da auch schon ein Lambda nehmen können…)

Ich hätte das ja ganz “herkömmlich”/bewährt so gemacht:

        ArrayList<File> files = new ArrayList<File>(/* sehr groß wählen */);
        ArrayDeque<File> adf = new ArrayDeque<File>(Arrays.asList(new File(""))); /* vernüftiger Dateiname */

        while (!adf.isEmpty()) {
            File file = adf.remove();
            if (file.isDirectory()) { /* erweitere hier usw. */
                File[] fa = file.listFiles();
                if (fa != null && fa.length != 0) { /* erweitere hier usw. */

                    for (File f : fa) {
                        files.add(file);
                        adf.add(f);
                    }
                }
            }
        }

        for (File f : files) {
            System.out.println(f);
        }
    }```

Ich wollte die Lösung unbedingt mit der Klasse Path realisieren, deshalb hab ich es so gemacht, wie es ist :slight_smile: Danke für Alle Antworten. Thema wäre aus meiner sicht gelöst.

Naja, meins ist wenigstens abwärtskompatibel bis 1.5

Der neue Schnickschnack ist natürlich selbstverständ. auch schön

Geschmacksfrage.

Edit:

Sry, hier ist ein Fehler,:

        ArrayList<File> files = new ArrayList<File>();
        ArrayDeque<File> adf = new ArrayDeque<File>(Arrays.asList(new File("D:\\")));

        while (!adf.isEmpty()) {
            File file = adf.remove();
            files.add(file);
            if (file.isDirectory()) {
                File[] fa = file.listFiles();
                if (fa != null && fa.length != 0) {
                    for (File f : fa) {
                        adf.add(f);
                    }
                }
            }
        }

        for (File f : files) {
            System.out.println(f);
        }
    }```


run:
D:
D:$RECYCLE.BIN



Es ist nicht direkt zu vergleichen mit Rekursion und adf und files wachsen schnell.

Entschuldige meinen Ton von gestern.

@CyborgBeta das ist ein sehr unschöner Code. Da bevorzuge ich dann doch lieber eine Variante mit Rekursion. Das geht auch mit den altbewährten Klassen/Funktionen also Rückwertskompatible aber schöner zu lesen.

public void geheDurchDasVerzeichniss(File verzeichniss){
  for (File datei:verzeichnis.listFiles()){
    if (datei.isDirectory()){
      geheDurchDasVerzeichniss(datei);
    }
    System.out.println(Datei);
  }
}

ist ungetestet und einfach nur mal schnell runtergetippt

verzeichnis.listFiles() könnte null liefern oder leer sein, deshalb hab ich das so gewählt. Trozdem Danke!

@CyborgBeta einen null check einbauen ist jetzt nicht so kompliziert

public void geheDurchDasVerzeichniss(File verzeichniss){
 if (verzeichnis!=null && verzeichnis.listFiles()!=null){
  for (File datei:verzeichnis.listFiles()){
    if (datei.isDirectory()){
      geheDurchDasVerzeichniss(datei);
    }
    System.out.println(Datei);
  }
 }
}