NetBeans Ordnernamen rekursiv auslesen und in Variable verarbeiten

denny86

Mitglied
Hallo zusammen,

ich bin nach knapp 5 Jahren endlich wieder mal in den Genuss gekommen ein JAVA-Programm mit GUI zu erstellen.
Zuletzt hab ich dies in meiner Ausbildung zum Fachinformatiker/Systemintegration gemacht. Ich hoffe ihr habt etwas Nachsicht mit mir, wenn ich nicht gleich alles verstehe. 🙂

Hier zu meinem Vorhaben:

Ich benötige ein Programm, welches mir eine Ordnerstruktur rekursiv ausliest und jeden Ordnernamen in ein Listen-Element einer HTML-Datei einfügt.

der JFrame ist mit NetBeans kein Problem.
Auch das selektieren des Haupt-Ordners sowie das Speichern der HTML-Datei ist für mich aktuell kein Problem.

Nun stehe ich jedoch vor der Herausforderung, dass ich die Ordnerstruktur rekursiv auslesen möchte um diese mit einer Variable weiter zu verarbeiten.

Ich habe schon diverse Beiträge in eurem Forum gelesen, aber stoße immer wieder darauf, dass Files in einem Ordner selektiert werden. Jedoch nicht die Ordner selbst.

Den Quellpfad selektiere ich aktuell mit dem JFileChooser und schreibe ihn in ein JTextField:
Java:
private void btnsrcMouseClicked(java.awt.event.MouseEvent evt) {                                   
    JFileChooser fc = new JFileChooser(); 
    fc.setDialogTitle("Quellordner auswählen...");
    fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    fc.showOpenDialog(null);
    File f = fc.getSelectedFile();
    txtsrc.setText(f.toString());
    }

Die Zieldatei gebe ich aktuell auch in ein JTextField aus:
Java:
 private void btndestMouseClicked(java.awt.event.MouseEvent evt) {                                     
    JFileChooser fc = new JFileChooser();
    fc.setDialogTitle("Speichern...");
    fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
    fc.showSaveDialog(null);
    File f = fc.getSelectedFile();
    txtdest.setText(f.toString());
    }

Kann mir jemand von euch einen Denkanstoß liefern mit welcher Methode ich mein Vorhaben am besten realisieren kann?

Danke im Voraus für eure Hilfe.

P.S.: Ich möchte hier bestimmt nicht, dass mir jemand meine "Hausaufgaben" macht. Ich benötige nur Unterstützung und versuche mich dann selbstständig ans Ziel zu hangeln. 🙄
 
Dein Problem ist also wie man rekursiv eine Ordnerstruktur durchläuft?
Soll diese denn im HTML abgebildet werden (mit der dazugehörigen Tiefe) oder sollen nur die Namen aufgelistet werden?
 
Hi Robat,

ich habe eine Ordnerstruktur mit mehreren verschachtelten Unterordnern:

Code:
Ordner 1
  Ordner 2
  Ordner 3
    Ordner 4
  Ordner 5
    Ordner 6
      Ordner 7
Ordner 8
Ordner 9
...
Hier muss ich jeweils den Ordnernamen in einen HTML Code schreiben, der folgendermaßen aussieht:
HTML:
<li>
    <img src="./icons/2219.png" alt="Ordner 1"/>
    <a href="../domain/Maps/ADSTree/Ordner 1.html" target="content">Ordner 1</a>
</li>

So hab ich ungefähr 30-40 Ordner.

Den HTML Code erzeuge ich dann mit einer for-Schleife pro Element.
Zumindest ist so mein Gedanke.

Für Vorschläge hierfür bin ich auch dankbar. 🙂

Mein Problem besteht aktuell darin, dass ich mit dem JFileChooser zwar Ordner durchsuchen kann und die beinhalteten Files rauskrieg (von mir aus auch gefiltert anhand der Dateiendung) aber nicht NUR die Ordnernamen selbst von jedem Ordner/Unterordner.

Hast du hierfür ne Idee bzw. n Vorschlag?

Wie erwähnt ist mein Java etwas eingerostet...
 
Mein Problem besteht aktuell darin, dass ich mit dem JFileChooser zwar Ordner durchsuchen kann und die beinhalteten Files rauskrieg (von mir aus auch gefiltert anhand der Dateiendung) aber nicht NUR die Ordnernamen selbst von jedem Ordner/Unterordner.
Indem du die Files hast, hast du doch auch alle Namen?
Für alle direkten Kinder musst du dann nur noch deren Kinder suchen, und für die das gleiche etc, am einfachsten Rekursiv
 
Kommt darauf an, ob ALLE Ordner einen einzigartigen Namen besitzen. In dem Fall wäre es recht einfach zu programmieren.
 
mrBrown hat gesagt.:
Indem du die Files hast, hast du doch auch alle Namen

Na die Files in den Ordnern sind für mich irrelevant!

Ich benötige die Ordnernamen selbst in einer Variable, da ich diese dann widerum in einen HTML Pfad übergeben muss.
Die Ordner brauch ich ohne Pfad.

Normal hab ich
C:\Ordner 1\ Ordner 2\File 1.html

In die Variable sollte nun also
String[ ] Ordner 1, Ordner 2,...

In der HTML sieht das dann so aus:
.\pfad\unterpfad\Ordner 1\...html
.\pfad\unterpfad\Ordner 2\...html

Hier hilft es mir nix, wenn ich die Filenamen bekomm.

Vielleicht versteh ich deinen Ansatz auch falsch. 🙂

@krgewb: Das kann ich ned sagen. Die Ordnerstruktur erstellt sich aus einem Programm namens Docusnap. Dieses Programm macht mir einen kompletten Netzwerkscan.
Die Ordnernamen ergeben sich aus den Gerätenamen im Netz.
 
Jeder Ordner ist ein File.
Und von jedem File kannst du den Namen bekommen.
Ok jetzt versteh ich deine Denkweise. Sorry da haben wir aneinander vorbei geredet.

Wenn ich das richtig verstehe, dann müsste ich dem JFileChooser einfach sagen, dass er mir mit DIRECTORIES_ONLY nur die Ordner ausgibt und diese dann in einer FOR-Schleife mit
Java:
File file[] = JFileChooser.getFiles()
einlesen.
 
Je nachdem, was du im Chooser auswählen willst ja.
Ich hab mir jetzt mal nen "Sucher" gebaut
Jedoch renne ich hier noch in nen Fehler, den ich aktuell nicht finde.
Java:
 static void search(File file) {
        if (file.isDirectory()) {
            File[] sBaum= file.listFiles();
            for (int i = 0; i < sBaum.length; i++) {
                System.out.println(sBaum[i].getParent()); //Dir ausgeben
                search(sBaum[i]);
            }
        }
    return sbaum;
}
im file übergeb ich das ausgewählte Verzeichnis und lass das rekursiv durchlaufen.
Jedoch bekomm ich jetzt für jedes File, welches im Ordner liegt auch den Ordnerpfad.
Heißt ich hab mehrmals hintereinander den selben Pfad im Output stehen.
Code:
C:\Ordner 1
C:\Ordner 1
C:\Ordner 1\Ordner2
C:\Ordner 1\Ordner2
C:\Ordner 1\Ordner2
Kann mir hier noch jemand weiterhelfen?
 
Warum denn sBaum.getParent()?
Ich hab s erst mit .getAbsolutePath(); versucht, aber da bekomm ich dann die Files mit, welche ich gar nicht haben möchte. So krieg ich nur den Ordnerpfad zurück, in dem das File liegt.
Das andere Problem ist aktuell noch, dass ich den kompletten Pfad zurückbekomme.
Dies könnte ich aber notfalls vorne abschneiden.
Aber vielleicht hast du da noch ne bessere Idee.

Aktuell steh ich hier grad total auf dem Schlauch. Da sieht man teils den Wald vor lauter Bäumen nicht mehr. 😳
 
Dann geh doch nicht alle Dateien durch, um deren Ordner zu bekommen, sondern gehe nur Ordner durch 😉

listFiles kannst du zB einen Fiiter übergeben, sodass du nur Order bekommst
 
Dann geh doch nicht alle Dateien durch, um deren Ordner zu bekommen, sondern gehe nur Ordner durch 😉

listFiles kannst du zB einen Fiiter übergeben, sodass du nur Order bekommst

Werd mir das ganze morgen mal anschauen.
Hab hierzu grad paar Ansätze gefunden, aber da müsste ich die Filter selbst bauen.
Konnte auf die Schnelle keine vordefinierte Filter-Funktion im listFiles() finden... 🙁

Müsste ja eigentlich nur alles rausfiltern was != ".*" ist...

Merk schon bin dafür heute nimma fit. 🙂
 
Probier's doch mal mit einem FileVisitor:

Code:
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

public class TestVisitor {

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

        // the directory to start with
        Path path = new File("/path/to/your/target/directory/").toPath();

        // iterate the file tree
        Files.walkFileTree(path, new FileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                System.out.println("DIRECTORY: " + dir);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                //System.out.println("FILE: " + file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
                System.out.println("SHIT HAPPENS: " + file);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                //System.out.println("VISTED DIRECTORY: " + dir);
                return FileVisitResult.CONTINUE;
            }
        });
    }

}

Wenn du nur eine der Methoden implementieren willst, kannst den SimpleFileEditor verwenden.

Cheers,
Andy
 
In seinem Code steht:
Java:
        if (file.isDirectory()) {
Und in seinem Beispiel im Eingangsbeitrag steht:
Java:
    fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);

Nachdem das ganze mit dem FileChooser nicht so ganz funktioniert wie es soll hab ich mir jetzt ne Methode mit File geschrieben:
Java:
    public void search(File file) {
        if (file.isDirectory()) {
            File[] sBaum= file.listFiles();
            for (int i = 0; i < sBaum.length; i++) {
                areaoutput.append(sBaum[i].getName()+"\n"); //Dir ausgeben
                search(sBaum[i]);
            }
        }
    }

Das funktioniert soweit auch ganz gut:
Code:
Text1.txt
U1
U1-1
Text2.txt
U1-2
Text3.txt
U1-2-1
Text4.txt
U1-3
Text5.txt
U2
Text6.txt
U3
Text7.txt
U3-1
Text8.txt

Mit dem .getName() bekomme ich nur den gewünschten Ordnernamen angezeigt.
Jedoch fehlt mir aktuell noch ne Idee, wie ich die beinhalteten Files (Text1-8.txt) rausfiltern kann.

Vielleicht hat hier noch jemand eine Idee. 🙂
 
Eigentlich war ich der Meinung, dass er das noch nicht hatte als ich meinen Beitrag geschrieben habe. Eventuell habe ich mich auch verlesen.
 
Anhand eurer Hilfe bin ich wirklich einen mega Schritt weiter! 😎 DANKE!

Jetzt steh ich aber noch vor einer Kleinigkeit, wo ich noch nach einer Lösung suche:

Ich hab mir jetzt alle Ordnernamen in eine ArrayList geschoben. Ebenso hab ich die ganzen Pfade (welche ich an einer anderen Stelle in meiner HTML-Datei benötige) in eine ArrayList geschrieben.
Java:
    File input; // Suchpfad
    File output; // Speicherpfad
    ArrayList<String> folderlist = new ArrayList<>(); // Ordnerliste
    ArrayList<String> pathlist = new ArrayList<>(); //Pfadliste
 
    public void search(File file) {
        int i;
        if (file.isDirectory()) {
            folderlist.add(file.getName()); //Ordner ausgeben
            pathlist.add(file.getPath()); //Pfad ausgeben
            File[] sBaum = file.listFiles();
            for (i = 0; i < sBaum.length; i++) {
                search(sBaum[i]);
            }
        }
    }

Nun müsste ich in der gesamten ArrayList pathlist den Einstiegs-Pfad abschneiden.
Heißt ich möchte die Anzahl der Zeichen in der Variable input lesen und diese Anzahl Zeichen in der ArrayList pathlist abschneiden.
Außerdem muss ich alle \ durch / ersetzen. (HTML-Pfade eben -.-)

Ich weiß zwar genau was ich brauch, aber mir fällt grad keine Möglichkeit ein, das einfach ohne großen Aufwand zu realisieren. 🙁

@Harry Kane:
Danke nochmals für deinen Tipp mit dem Umbau der Ausgabe vor der for-Schleife. Hat prima geklappt.

EDIT: Hab mich grad noch etwas durchgelesen und herausgefunden, dass ich mit
Java:
String s = input.toString();
int a = s.length();
die Zeichenlänge auslesen und dann mit .substring(a) beschneiden könnte. Aber wie bring ich das ganze so zusammen, dass mir die übrig bleibende Zeichenkette wieder in der ArrayList landet? 😱
 
Zuletzt bearbeitet:
Dazu gibt es die replace-Methode.
Java:
full_string = full_string.replace("/", "\\");
Ein einfacher Backslash würde wegen dem Anführungszeichen zu einer Repräsentation vom Anführungszeichen führen.

Bezüglich substring:
Es gibt noch eine substring-Methode mit anderer Parameterliste:
Java:
substring(int beginIndex, int endIndex)
 
Bezüglich substring:
Es gibt noch eine substring-Methode mit anderer Parameterliste:
Java:
substring(int beginIndex, int endIndex)
Ich hab das mal so gelöst und es funktioniert auch wunderbar:
Java:
String s = input.toString(); //Einlese-Pfad
int a = s.length();
for(int i = 0; i < pathlist.size(); i++){
   String t = pathlist.get(i);
   t = t.substring(a);
   pathlist.set(i, t);
}
Somit zieht er mir die Anzahl Zeichen des Einstiegs-Pfads von meinen Pfaden ab und mir bleibt im Endeffekt der benötigte .\Ordner1\Ordner2\Ordner3 🙂

Dazu gibt es die replace-Methode.
Java:
full_string = full_string.replace("/", "\\");
Ein einfacher Backslash würde wegen dem Anführungszeichen zu einer Repräsentation vom Anführungszeichen führen.
Diese Funktion kann ich (entweder aus Unwissenheit oder einfachem "geht nicht") in einer ArrayList<String> so nicht nutzen, da ich den Listen-Index nicht übergeben kann. 😕

Habe es versucht mit der Funktion Collections.replaceAll(pathlist,"\\","/") zu lösen, aber hier hab ich vorher/nacher immer noch den "\" drin, statt "/". 😡
EDIT: Ich hab auch (zur Sicherheit) die Zeichen umgedreht "/" <-> "\\"
 
Collections.replaceAll ersetzt die Werte in der Collection mit anderen, das hat nichts mit der replace-Funktion des Strings zu tun 😉

Passender wäre in de Fall List#replaceAll, dem übergibst du eine Funktion, die auf jedes Element angewandt wird.
 
Das Replacement bringt mich noch zur Verzweiflung. 😡

Hab versucht die Zeichen mit String.replace(oldChar, newChar) sowie mit String.replace(CharSequence String, charSequence replacement) zu ändern, da List.replaceAll() eine regex benötigt und mir eine Exception auswirft.

Dazu hab ich mir folgendes gebastelt:
Java:
for(int i = 0; i < folderlist.size(); i++){
    String t = folderlist.get(i); // Zeile in String einlesen
    t = t.replace("\\", "/"); // Zeichen ersetzen (Test 1 String)
    t = t.replace('\\', '/'); // Zeichen ersetzen (Test 2 Char)
    folderlist.set(i, t); // String in Zeile zurückschreiben
}

Wenn ich den Code ausführe, dann verschwinden mit die \ aus dem Pfad, aber die / fehlen. Somit hab ich dann alle Ordnernamen aneinander gereiht OHNE Unterteilung. 😵
 
Hab versucht die Zeichen mit String.replace(oldChar, newChar) sowie mit String.replace(CharSequence String, charSequence replacement) zu ändern, da List.replaceAll() eine regex benötigt und mir eine Exception auswirft.
Da verwechselst du was List.replaceAll und String.replace/String.replaceAll haben nichts miteinander zu tun 😉

Wenn ich den Code ausführe, dann verschwinden mit die \ aus dem Pfad, aber die / fehlen. Somit hab ich dann alle Ordnernamen aneinander gereiht OHNE Unterteilung. 😵
Kann ich nicht nachvollziehen, der gepostetet Code funktioniert ohne Probleme.
 
Ich könnt mich ohrfeigen!

Mir ist eben aufgefallen, dass ich die falsche ArrayList bearbeitet habe. 😱
In meiner folderlist sind ja gar keine \ enthalten.

Nun funktioniert alles wie gewollt. 🙂

Aber eine kleine Unstimmigkeit macht mich grad noch stutzig.

Ich hab mit t = "." + t; zwecks HTML-Negation im Ordner-Einsprungspunkt an jeden String einen . voran gesetzt.

Jetzt ist mir aufgefallen, dass meine ArrayList in der ersten Zeile NUR einen . enthält. Was mir sagt, dass die erste Zeile "leer" ist.

Zur Veranschaulichung nochmals der gesamte relevante Code:
Java:
File input; // Suchpfad
ArrayList<String> folderlist = new ArrayList<>(); // Ordnerliste
ArrayList<String> pathlist = new ArrayList<>(); //Pfadliste

//MouseButtonFunktion zum Pfad auswählen
private void btnsrcMouseClicked(java.awt.event.MouseEvent evt) {                                   
    JFileChooser fc = new JFileChooser(); // FileChooser erstellen
    fc.setDialogTitle("Quellordner auswählen..."); // Titel setzen
    fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); // NUR Verzeichnisse anzeigen
    fc.setCurrentDirectory(new File("C:/")); // HOME-DIR setzen
    fc.showOpenDialog(null); // Dialog öffnen
    input = fc.getSelectedFile(); // Selektierten Pfad in Variable übergeben
        txtsrc.setText(input.toString()); // Pfad zur Veranschaulichung in GUI setzen
}   

// Suchfunktion ausführen
private void proceedMouseClicked(java.awt.event.MouseEvent evt) {                                     
    search(input);
}
// Suchfunktionsklasse
private void search(File file) {
        if (file.isDirectory()) {
        folderlist.add(file.getName()); //Ordner ausgeben
        pathlist.add(file.getPath()); //Pfad ausgeben
        File[] sBaum = file.listFiles();
        for (int i = 0; i < sBaum.length; i++) {
            search(sBaum[i]);
        }
    }
}

// Benötigte Daten erhalten
String s = input.toString(); // File to String
int a = s.length(); // String-Länge ermitteln zum abschneiden
for(int i = 0; i < pathlist.size(); i++){
    String t = pathlist.get(i); // Zeile in String einlesen
    t = t.substring(a); // Haupt-Pfad abschneiden
    t = "." + t; // Punkt anfügen
    pathlist.set(i, t); // String zurückschreiben
}

for(int i = 0; i < pathlist.size(); i++){
    String t = pathlist.get(i); // Zeile in String einlesen
    t = t.replace("\\", "/"); // Zeichen erstezen
    pathlist.set(i, t); // String zurückschreiben
}

Meine Frage ist hier nun: WOHER kommt die erste leere Zeile? 😕
Kann es sein, dadurch, dass ich den String abschneide, dass mir in der 1. Zeile der Haupt-Pfad ausgegeben wird und ich hier die Zeichen alle abschneide?

Dann müsste ich theoretisch die 1. Zeile in der pathlist löschen.

Und wie kann ich sicherstellen bzw. kontrollieren, dass ich in der pathlist sowie der folderlist die gleiche Anzahl Zeilen habe, damit ich beim HTML-Schreiben immer die gleiche Zeile erwische?
In der Pathlist soll in Zeile 1 z.B. .\Ordner1\Ordner2\Ordner3 stehen und
in der Folderlist Ordner3
 
Mal so zwischenrein eine kosmetische Frage:

Ist es egal, ob ich hier mit "for"-Schleifen arbeite oder wäre es performance-technisch besser und schöner, wenn ich für die ArrayList<> einen ListInterator<> nutze und mit einer do { } while Schleife arbeite?
 
schöner wäre eine for-each oder sogar forEach 😉
Klar für die areaoutput kann ich locker eine forEach verwenden, aber in einer ArrayList muss ich ja z.B. beim .set() einen index mitgeben.

Bei einer for hab ich durch
for (int i = 0; i < var.size(); i++)
den Index i

Aber bei einer forEach wird ja der Inhalt der Zeile direkt an eine Haltevariable übergeben
for (String i: var)
wodurch ich keinen Index habe.
 
Deshalb würde ich dafür replaceAll nutzen - alternativ iterator.
Auf Indexbasiert würde ich verzichten, ist aber auch zT Geschmacksache
 
Mit dem replaceAll komm ich aktuell überhaupt ned zurecht.
Aber ich denke wenn soweit erst mal alles funktioniert, werd ich statt dem Index nen Iterator nutzen und die for-Schleifen (soweit möglich) durch do { ..next() } while ...hasNext() ersetzen. 🙂

Wichtig ist mir jetzt erstmal, das Problem noch zu lösen:
#32
 
Mit dem replaceAll komm ich aktuell überhaupt ned zurecht.

pathlist.replaceAll(t -> t('\\', '/'));

jedes Element in pathlist (=t) wird einfach ersetzt mit dem Ergebnis des replace 😉

Aber ich denke wenn soweit erst mal alles funktioniert, werd ich statt dem Index nen Iterator nutzen und die for-Schleifen (soweit möglich) durch do { ..next() } while ...hasNext() ersetzen. 🙂
blieb lieber bei for 😉
 
Hallo.

Ich kann nur empfehlen auch mal den Debugger zu verwenden wenn sowas wie:
Meine Frage ist hier nun: WOHER kommt die erste leere Zeile?
kommt.

Früher oder Später musst du damit sowieso arbeiten.

Im übrigen ein Beispiel:

Java:
String a = "C:\\windows\\system\\";
System.out.println(a);
System.out.println(a.substring(a.length()));

Ausgaben:
C:\windows\system\
Leerzeichen

Grüße
 
Zuletzt bearbeitet:

Zurück
Oben