# Verzeichnis ausgeben mit Unterverzeichnissen und einzelnen Dateien



## masul (4. Apr 2012)

Hallo Leute! 
Wir haben als Übung im Studiengang Medieninformatik, 2. Semester, die Aufgabe bekommen, anhand eines angegebenen Pfades alle Verzeichnisse und Unterverzeichnisse auszugeben und auch einzelne Dateien anzeigen zu lassen. 
Hab schon ein Programm geschrieben, nur leider macht es nicht immer das, was es machen soll und liefert zudem nicht immer die korrekte Anzahl an Dateien.

Komme einfach nicht weiter! 

Es ist wirklich dringend!!!

Danke euch im Voraus!

```
public static void printAll(File path) {
       PrintWriter out = new PrintWriter(System.out,true);
       File[] fileArray = path.listFiles();
       if (fileArray != null) {
	for (int i = 0; i < fileArray.length; i++) {
	       if (fileArray[i].isDirectory()) {
		if (fileArray.length<10) {
		    out.println("Verzeichnis"+ fileArray[i].getAbsolutePath() + "[mit 0" + fileArray.length + " Dateien]");
		} else {
		    out.println("Verzeichnis "+ fileArray[i].getAbsolutePath() + "[mit " + fileArray.length  + " Dateien]");
					 }
	       printAll(fileArray[i]);
                  } else { 
		    out.println("Datei " + fileArray[i].getName());
	       }
	 }
       }
       out.close(); 
}
```


----------



## HimBromBeere (4. Apr 2012)

Gibt´s dazu ´ne konkrete Frage? In welcher Zeile hängt´s denn, gibt es Fehlermeldungen, was soll denn passieren und was passiert stattdessen? Fragen über Fragen...

EDIT: Wohin gehört das 
	
	
	
	





```
else
```
 in Zeile 13?


----------



## Jodo (4. Apr 2012)

Wie HimBromBeere schon sagt, können wir deine Fehler nicht erraten .

*-Edit-*
Schwachsinn von mir entfernt 

Aber wieso unterscheidest du bei den Verzeichnislängen?


----------



## SlaterB (4. Apr 2012)

für Unterverzeichnisse bietet sich Rekursion an:
wenn du nicht nur die Ausgabe 'mit x Dateien' haben willst, sondern diese Datein + evtl. weitere Unterverzeichnisse auch,
dann wieder printAll() für diese Unterverzeichnis aufrufen

-----
nur wegen Einfügen einer 0 bei < 10 den ganzen out-Befehl zu wiederholen ist unschön,
lege dir lieber eine Variable an:
String fLength = ... mit if/else oder ternären Operator und diesen String dann im langen nur einmal programmieren out-Befehl


----------



## masul (4. Apr 2012)

Also er gibt mir z.B. sowas aus: 

Verzeichnis     C:\Users\acer\Desktop\Gregor Staub - MegaMemory[mit 05 Dateien]
Verzeichnis     C:\Users\acer\Desktop\Gregor Staub - MegaMemory\Gregor Staub - Mega Memory -                   Selbstlehrgang für Gedächtnistraining[mit 02 Dateien]
Verzeichnis     C:\Users\acer\Desktop\Gregor Staub - MegaMemory\Gregor Staub - Mega Memory -                   Selbstlehrgang für Gedächtnistraining\CD1[mit 12 Dateien]
Datei              artist - Track 1.mp3
Datei               artist - Track 2.mp3


Diese Ausgabe beinhaltet aber leider nicht alle vorhandenen Verzeichnisse. 

Die Aufgabenstellung für diese Methode: 
/** Gibt alle Verzeichnisse und Dateien in dem Verzeichnis, das durch den Parameterwert path beschrieben wird, in der untenstehenden Form aus. Es werden durch Rekursion auch alle Unterverzeichnisse und deren Inhalt mit ausgegeben.*/

Form der Ausgabe:
Verzeichnis   Z:/java/project/PR2/src
Verzeichnis   Z:/java/project/PR2/src/a03 [mit 02 Dateien]
Datei                  Aufgabe2.java
Datei                  Aufgabe2ersterversuch.java  [mit 02 Dateien]

usw.




Fehlermeldungen gibt es keine. Das Programm gibt bei mir die oben angeführte Ausgabe aus, aber darin fehlen viele Ordner und Dateien.




```
public static void main(String[] args) {
		DirContent test = new DirContent();
		test.printAll("C:\\Users\\acer\\Desktop");
}
```
Das ist übrigens meine main-Methode..


----------



## masul (4. Apr 2012)

Das 'else' in Z.13 gehört zum ersten 'if' nach der for-Schleife.


----------



## Jodo (4. Apr 2012)

Ich habs grade mal bei mir getestet. Wenn ich anstatt deinem 
	
	
	
	





```
PrintWriter
```
 das normale 
	
	
	
	





```
System.out.println()
```
 benutze, funktioniert es bei mir. Suche grad noch wo der Writer vorher geschlossen wird/werden könnte.

*-Edit-*
Wo auch noch ein Denkfehler drin stecken müsste: Du prüfst ob eine File im Array ein Verzeichnis ist und gibst aber immer die Anzahl an Dateien aus die im aktuellen Verzeichnis liegen, nicht in dem "gefundenen".


----------



## Gast2 (4. Apr 2012)

Jodo hat gesagt.:


> Suche grad noch wo der Writer vorher geschlossen wird/werden könnte.


Vermutlich in Zeile 18 wo der close() Befehl steht  Wenn er beim ersten Verzeichnis ganz unten in der Rekursion angekommen ist wird der Stream geschlossen.


----------



## Jodo (4. Apr 2012)

EikeB hat gesagt.:


> Vermutlich in Zeile 18 wo der close() Befehl steht  Wenn er beim ersten Verzeichnis ganz unten in der Rekursion angekommen ist wird der Stream geschlossen.



Ja, habs etwas falsch formuliert, merk ich auch grad 
Versteh nur grad selbst nicht, wieso das Problem auftritt. Er geht ja mit ner Tiefensuche vor und in jedem Rekursionsschritt wird ein neuer PrintWriter-Objekt erzeugt. Ergo bleibt der Äußerste ja offen solange er die Dateien/Verzeichnisse im obersten Verzeichnis durchgeht.

*-Edit-*
Ok. Problem (wohl) gefunden. Da dem PrintWriter der 
	
	
	
	





```
System.out
```
 übergeben wird, wird dieser mitgeschlossen? Jedenfalls ist 
	
	
	
	





```
System.out
```
 danach nichtmehr benutzbar.


----------



## irgendjemand (4. Apr 2012)

@TO
die formatierung ist ja nicht gerade die beste
dann noch : warum PrintWriter über System.out und den auch noch closen ? du kannst dierekt System.out.println() callen ... denn System.out ist vom typ PrintStream
auch hast du einen logikfehler drin : die ausgabe der anzahl ist die im aktuellen verzeichnis ... aber nicht die dessen was du gerade ausgegeben hast ... dafür müsstest du dann sowas nach der art schreiben : [c]fileArray_.listFiles().length[/c] ... was aber eigentlich einen rekursionsschritt tiefer stehen sollte ...

alles in allem zwar schon mal ein guter ansatz ... aber mit ner menge logik-fehler_


----------



## Jodo (4. Apr 2012)

irgendjemand hat gesagt.:


> @TO
> die formatierung ist ja nicht gerade die beste



Dann möchte ich dich aber darauf hinweisen, dass deine Groß-/Kleinschreibung und Interpunktion in etwa seiner Code Formatierung entsprechen..


----------



## Gas3t (4. Apr 2012)

Ich bin im Gleichen Kurs wie "masul" und habe meine Klasse sehr ähnlich geschrieben.
Auch die geschilderten Probleme sind bei mir gleich; wobei ich aber z.B. das mit dem Printwriter behoben habe (einfach System.out.println geschrieben...).

Ein anderes Problem, welches mir aufgefallen ist, dass das erste Unterverzeichnis von "path" bei mir nicht ausgegeben wird, sondern lediglich die Dateien.
Kann dies mit der Rekursion zusammenhängen ?


----------



## Jodo (4. Apr 2012)

Gas3t hat gesagt.:


> Ein anderes Problem, welches mir aufgefallen ist, dass das erste Unterverzeichnis von "path" bei mir nicht ausgegeben wird, sondern lediglich die Dateien.
> Kann dies mit der Rekursion zusammenhängen ?



Das Startverzeichnis, oder wirklich das erst Unterverzeichnis? Ist das Verzeichnis zufällig lexikographisch der erste Eintrag im System, und dadurch auch im Array, und du hast ne falsche Schleifenvariable?

Zeig mal etwas Code, dann kann man dir auch helfen.


----------



## Gas3t (4. Apr 2012)

Ich glaube du hast Recht. Das ist das Startverzeichnis - im meinem Fall "prtest" (s. Code) - welches wohl übersprungen wird.
Der Rest scheint jetzt aber ganz gut zu laufen.


```
public class DirContent{
	
	public static void main(String[] args){
		printAll("C:\\Users\\Nessi\\Desktop\\prtest");
	}
	
	/** Hilfsmethode String-Objekt --> File-Objekt */	
	public static void printAll(String path){
		printAll(new File(path));
	}
	
	/**
	 * Gibt alle Verzeichnisse und Dateien in dem Verzeichnis aus.
	 * Durch Rekursion werden auch alle Unterverzeichnisse und deren Dateien ausgegeben.
	 * @param path steht stellvertretend für den Verezeichnispfad, wird von <code> main </code> übergeben.
	 */
	public static void printAll(File path){
		File [] fileList = path.listFiles();
		if (fileList != null){
			for (int i =0; i<fileList.length; i++){
				if (fileList[i].isDirectory()){
					int length = fileList[i].listFiles().length;
					if (length<10){
						System.out.println("Verzeichnis "+ fileList[i].getAbsolutePath() + " [mit 0" + length + " Dateien]");
					}
					else{
						System.out.println("Verzeichnis "+ fileList[i].getAbsolutePath() + " [mit " + length + " Dateien]");
					}
					printAll(fileList[i]);		
				}
				else{
					System.out.println("Datei \t\t" + fileList[i].getName());
				}	
			}
		}
	}
```


----------



## Jodo (4. Apr 2012)

Bei Rekursion musst du beachten, dass die Methode auf jeder Rekursionsebene exakt das selbe tun sollte mit der selben Art von Daten. Was du machst ist, du nimmst alle Unterdateien des aktuellen Verzeichnisses und prüfst dessen Inhalt. Du kümmerst dich aber gar nicht drum, dass beim ersten Aufruf das Startverzeichnis ja auch scho gelistet werden sollte.

Lösung deines Problems ist, wie schon gesagt, das selbe Verhalten für jede Ebene, sprich: 
Du prüfst ob das aktuelle File-Objekt ein Verzeichnis ist, wenn ja gibs aus.
Für alle anderen File's prüfen ob sie eine Datei oder ein Verzeichnis sind und gegebenenfalls rekursiv absteigen.(was du ja schon richtig machst).


----------



## Gas3t (4. Apr 2012)

Jodo hat gesagt.:


> Du prüfst ob das aktuelle File-Objekt ein Verzeichnis ist, wenn ja gibs aus.



Das mache ich doch in Zeile 21. Und die Rekursion ist ja in Zeile 29.
Ich bin, glaube ich, etwas überfordert... :-/

Des weiteren sehe ich gerade, dass er bei der Anzahl der Dateien "alles", d.h. auch die Verzeichnisse, mitrechnet. Hier müsste ich bei dem length()-Ausdruck etwas ändern, oder ?

Vielen Dank für die ganzen hilfreichen Antworten !


----------



## Jodo (4. Apr 2012)

Gas3t hat gesagt.:


> Das mache ich doch in Zeile 21. Und die Rekursion ist ja in Zeile 29.
> Ich bin, glaube ich, etwas überfordert... :-/


Ganz cool bleiben  Überleg dir immer Schritt für Schritt was du machen musst (auch mal ohne Java Code) und das setzt du dann meist 1:1 in Java um. Du machst bei dir nicht ganz exakt, das was du tun solltest. Da du ja das Startverzeichnis mit drin haben willst, ist das erste was du machen musst: Prüfen ob das aktuelle File (path bei dir) ein Verzeichnis ist und dann ausgeben.
Also sowas in der Art


```
public static void printAll(File path) {
    File[] fileArray;

    if (path.isDirectory) {
        //Verzeichnis Ausgabe und alle Dateien im Verzeichnis holen
    }

    if (fileArray != null) {
        //hier dein bisheriger Code, nur dass du hier nichtmehr die Verzeichnisse ausgibst
        //sondern nur den rekursiven Aufruf tätigst, falls es ein Verzeichnis ist.
    }
}
```

[EDIT]Ob in die Anzahl der Dateien auch die Verzeichnisse mit eingerechnet werden sollen ist Auslegungsache bzw. abhängig von der Aufgabenstellung. Ich würd's dazu machen, wenn in der Aufgabe nichts anderes steht.[/EDIT]


----------



## irgendjemand (5. Apr 2012)

ich hatte mal langeweile und hab euch mal auf die schnelle was zusammengebastelt


```
import java.io.File;
import java.io.IOException;
public class RecursiveFileLister
{
	public static void main(String[] args) throws IOException
	{
		if(args.length!=1)
		{
			System.err.println("USAGE : java RecursiveFileLister <PATH>");
			System.exit(1);
		}
		File path=new File(args[0]);
		(new RecursiveFileLister()).list(path);
	}
	private RecursiveFileLister() { }
	private void list(File path) throws IOException
	{
		path=path.getCanonicalFile();
		if(path.isFile())
		{
			System.out.println("Datei : "+path.getAbsolutePath());
			return;
		}
		if(path.isDirectory())
		{
			int subdirs=0;
			int files=0;
			File[] subfiles=path.listFiles();
			if(subfiles==null||subfiles.length==0)
			{
				System.out.println("Ordner : "+path.getAbsolutePath()+ " (0 Ordner, 0 Dateien)");
				return;
			}
			for(int i=0; i<subfiles.length; i++)
			{
				if(subfiles[i].isFile())
				{
					files++;
				}
				if(subfiles[i].isDirectory())
				{
					subdirs++;
				}
			}
			System.out.println("Ordner : "+path.getAbsolutePath()+" ("+subdirs+" Ordner, "+files+" Datei"+((files==1)?")":"en)"));
			for(File subfile : subfiles)
			{
				list(subfile);
			}
			return;
		}
		System.err.println("UKNOWN TYPE");
	}
}
```

ich gebe euch den tipp in eurem eigenen interesse diesen code NICHT 1-zu-1 zu kopieren ... weil ein solcher programmierstil dürfte eurem dozenten auffallen *foreach , ternary operator , OOP*

es soll euch aber den leitgedanken geben

ich hab mal quick'n'dirty die IOException von File.getCanonicalFile() einfach weitergeworfen

*zeile 18 ist wichtig um einen ausgabe-bug zu verhindern wenn ein komplettes laufwerk oder ein relativer pfad angegeben wurde
zeile 29 : prüfung auf NULL wichtig da dies z.b. auftreten kann wenn auf ein verzeichnis keine zugriffsrechte vorhanden sind
*zeile 52 : falls ein eintrag gefunden wird der WEDER File NOCH Directory ist *unter unix z.b. sockets oder anderer kram unter z.b. /dev/*


----------



## masul (5. Apr 2012)

super ich danke euch allen


----------

