NIO File Tree in XML umwandeln

Vince42

Mitglied
Moin,

ich möchte gerne mit NIO Files.walk() und JAXB einen Verzeichnisbaum rekursiv in eine XML-Datei umwandeln. Mein aktueller Stand sieht wie folgt aus:
Java:
package org.nodez.reader;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/*
* Convert file structure into tree datatype
* Version: 0.1
* Date: 2017-11-26
*/
public class Filesystem {
 
  // Constants
  private static final String OUTPUT_FILE = "q:\\project\\nodez\\output\\FilesystemTree.xml";
 
  // Variables
  private static Document doc;
 
  public static void main(String[] args) {
    createOutputFile();
    Path root = Paths.get(args[0]);
    try (Stream<Path> stream = Files.walk(root)) {
      Element node = doc.createElement("node");
      Attr name = doc.createAttribute("name");
      name.setValue("..."); // <-- how do I get the name of the folder or file?
      // node.setAttribute("name", "...");
      doc.appendChild(node);
    } catch (IOException e) {
      e.printStackTrace();
    }
    writeOutputFile();
  }
 
  private static void createOutputFile() {
    try {
      DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
      Document doc = docBuilder.newDocument();
      Element rootElement = doc.createElement("tree");
      doc.appendChild(rootElement);
    } catch (ParserConfigurationException e) {
      e.printStackTrace();
    }
  }
 
  private static void writeOutputFile() {
    try {
      TransformerFactory transformerFactory = TransformerFactory.newInstance();
      Transformer transformer = transformerFactory.newTransformer();
      DOMSource source = new DOMSource(doc);
      StreamResult result = new StreamResult(new File(OUTPUT_FILE));
      transformer.transform(source, result);
      System.out.println("File saved!");
    } catch (TransformerException e) {
      e.printStackTrace();
    }
  }

}

Es ist leider ewig her, daß ich mal mit Java programmiert habe, daher bin ich für jeden Verbesserungsvorschlag dankbar. Ich habe leider nicht verstanden, wie ich dem Attribut "name" den Namen des aktuellen Ordners oder der Datei zuweise. Vermutlich ist es trivial, aber ich konnte in den Codeschnipseln und Dokumentationen nichts passendes finden - oder ich habe es gelesen und nicht verstanden.

Vielen Dank im voraus!
 

truesoul

Top Contributor
Hallo.

Also einem Attribute den Namen zu geben ist weniger Sinnvoll. Weil die unerlaubte Zeichen wie z. B \ eine Fehlermeldung aller Voraussicht erzeugen würden.

Denke das ein Knoten so aussehen könnte:

Code:
<directory>
    <name>C:\\</name>
    <files>
        <file>
            <name>Test</name>
            <extension>exe</extension>
        </file>   
        <file>
            <name>Test</name>
            <extension>exe</extension>
        </file>
    <files>
    <directories>
        <directory>.....</directory>
    </directories>
<directory>

Ein Beispiel wie das gehen könnte: https://www.mkyong.com/java/how-to-create-xml-file-in-java-dom/

Aber ehrlich gesagt kann so eine XML echt bescheiden aussehen, wenn du z. B von Laufwerk C aus startest.
Die Rechte musst du auch noch beachten. Nicht in allen Ordner darfst du rein ....

Grüße
 

Vince42

Mitglied
Danke für den Beitrag! Die Web Site von mkyong hatte ich auch als Ausgangsbasis für den Code genommen. Jetzt stellt sich mir die Frage, wie in der Code-Zeile "name.setValue("...");" der Name der Datei aus dem Objekt stream über eine Methode oder ein Property ausgelesen werden kann.
Ich habe auch etwas über Marshalling im Zusammenhang mit JAXB gelesen, was tendentiell interessant klang, um Objekte in XML und XML in Objekte umzuwandeln - wäre das eher der Weg, der hier zu verfolgen wäre?
 

truesoul

Top Contributor
Ein Beispiel wie man z.B alle Ordner in einer XML speichert.

Java:
        // root elements
        Document doc = docBuilder.newDocument();
        Element rootElement = doc.createElement("hierarchy");
        doc.appendChild(rootElement);

        Element dirsElement = doc.createElement("directories");
        rootElement.appendChild(dirsElement);

        Files.walk(Paths.get("D:\\example")).filter(new Predicate<Path>() {

            @Override
            public boolean test(Path t) {
                return Files.isDirectory(t) && Files.isReadable(t) && Files.isWritable(t);
            }
        }).forEach(new Consumer<Path>() {

            @Override
            public void accept(Path t) {
                Element dirElement = doc.createElement("directory");
                dirElement.appendChild(doc.createTextNode(t.toAbsolutePath().toString()));
                dirsElement.appendChild(dirElement);

                // Hier ein Aufruf um alle Dateien im Ordner in dirElement zu hängen
                try {
                    Files.walk(t).filter(Files::isRegularFile).forEach(System.out::println);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

Es fehlt natürlich noch die Dateien dem Knoten <Files></Files> hinzufügen. Für dein anliegen brauchst du kein Marshalling.

Grüße
 

Vince42

Mitglied
Das hat schon mal sehr gut funktioniert - danke nochmal. Ich mußte erstmal noch ein paar Java-Docs lesen, aber ich glaube, daß ich größtenteils verstanden habe, was der Code macht. Jetzt habe ich noch ein paar Anschlußfragen:
  • Wie schaffe ich es, daß der Output "pretty" ist, dh alles mit Zeilenumbrüchen und Einrückungen versehen ist?
  • Wie ermittle ich am besten die Hierarchietiefe, um die Elemente ordnungsgemäß zu verschachteln?
  • Wie kann ich das Erzeugungsdatum, das Datum der letzten Änderung und die Dateigröße ermitteln? Läuft das über BasicFileAttributes?
  • Da ich mit Attributen arbeiten muß: der Funktionsaufruf 'node.setAttribute("size", 1024);' liefert einen Fehler, da setAttribute nur Strings als zweiten Parameter akzeptiert. Ich habe leider keine Funktionsvariante gefunden, die numerische Werte erlaubt, nur boolesche - es kann aber auch gut sein, daß ich zu blind war. :)
  • Und noch eine Mini-Frage: Das erste Element sollte nicht das Root-Element sein - soll ich das einfach per "wenn es das erste Element ist, erzeuge kein Element" machen oder gibt es einen eleganteren Weg?
Cheers
Vince
 

truesoul

Top Contributor
Zu 1.
Java:
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

Zu 2.
Du erhälst ein Path Objekt, damit hast du auch die Möglichkeit den Ausgangsverzeichnis zu bekommen.
Jetzt musst du dir nur eine Logik ausdenken, wie du zu jedem Path ein Element abspeicherst.
Das heißt du erstellst ein Knoten für C:\\Ordner 1\\ und dazu ein Element und speicherst beide Informationen und dann gehst du bei jedem Ordner und Prüfst ob das Ausgangsverzeichnis schon vorhanden ist, und fügst dem Directory->Directoeries->Neues Element hinzu.

Zu 3.
https://docs.oracle.com/javase/tutorial/essential/io/fileAttr.html

Zu 4.
Vergiss setAttribute() und erzeuge für jede Information ein Element.
Java:
<file>
<name></name>
<extenstion></extension>
<last_modified></last_modified>
usw...
</file>

Zu 5.
Meinst du z. B das Element "hierarchy"? Wenn ja, dann lass es weg und fange direkt mit "directories" an.

Grüße
 

mrBrown

Super-Moderator
Mitarbeiter
Musst du Files.walk() nutzen?
Wesentlich leichter ist es vermutlich, rekursiv selbst durch den Baum zu laufen.
 

Vince42

Mitglied
@truesoul Vielen Dank für Deine Tips! Ich bin leider jetzt erst dazu gekommen sie umzusetzen, aber es funktioniert alles bestens.

Zu 4.
Vergiss setAttribute() und erzeuge für jede Information ein Element.
Die Defnition des XSD liegt leider nicht in meiner Hand - ich muß mich an die Vorgaben halten. ;)

Musst du Files.walk() nutzen?
Wesentlich leichter ist es vermutlich, rekursiv selbst durch den Baum zu laufen.
Muß ich nicht. Ich hatte irgendwo gelesen, daß Files.walk() schneller und aktuell "state of the art" sei - aber ich erkenne die Probleme, welche die "Nicht-Rekursion" mit sich bringt - es ist definitv eine Überlegung wert und eine weitere schöne Übung.

Vielen Dank für Eure Hilfe - sie hilft mir wirklich sehr beim Einstieg!

Cheers
Vince
 

Vince42

Mitglied
Ich habe jetzt die iterierende Version hinbekommen - so weit so gut:
Java:
package org.nodez.fetch;

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.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Filesystem3 {

  // Constants
  private static final String ROOT_FOLDER = "q:\\project\\nodez\\java";
  private static final String OUTPUT_FILE = "q:\\project\\nodez\\output\\FilesystemTree.xml";
 
  // Variables
  private static Document doc;
  // private static Element parent;
 
  public static void main(String[] args) {
   
    try {
      DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
      doc = docBuilder.newDocument();
      Element tree = doc.createElement("tree");
      tree.setAttribute("name", ROOT_FOLDER);
      doc.appendChild(tree);
      Path root = Paths.get(ROOT_FOLDER);
      processChildren(tree, root);
      try {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(new File(OUTPUT_FILE));
        transformer.transform(source, result);
        System.out.println("File saved!");
      } catch (TransformerException e) {
        e.printStackTrace();
      }

    } catch (ParserConfigurationException e) {
      e.printStackTrace();
    }
  }

  private static void processChildren(Element parentElement, Path parentPath) {
    File[] list = parentPath.toFile().listFiles();
    if (list != null) {
      for (File item : list) {
        Element node = doc.createElement("node");
        node.setAttribute("name", item.getName());
        try {
          BasicFileAttributes attributes = Files.readAttributes(parentPath, BasicFileAttributes.class);
          node.setAttribute("created", String.valueOf(attributes.creationTime()));
          node.setAttribute("modified", String.valueOf(attributes.lastModifiedTime()));
          if (item.isDirectory()) {
            parentElement.appendChild(node);
            processChildren(node, Paths.get(item.getAbsolutePath()));
          } else {
            node.setAttribute("size", Long.toString(attributes.size()));
            parentElement.appendChild(node);
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }   
  }

}

Es gibt sicherlich noch gute Ideen, was man hier refactoren könnte - immer her mit den Vorschlägen!
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
L File Tree Node ausgeben Java Basics - Anfänger-Themen 2
L File Tree rekursiv Java Basics - Anfänger-Themen 10
Timo12345 JNLP File mit Java öffnen Java Basics - Anfänger-Themen 2
I Bild richtig speichern / Hochkant im File Explorer, nach Upload vertikal Java Basics - Anfänger-Themen 9
R File.pathSeparator und File.separator Java Basics - Anfänger-Themen 46
KeinJavaFreak Erste Schritte Java "Executable Jar File" nicht vorhanden Java Basics - Anfänger-Themen 1
izoards Prunsrv - Windows Service - .bat file starten Java Basics - Anfänger-Themen 84
I File Uploader... Statusanzeige, Berechnung des Status etc. Java Basics - Anfänger-Themen 0
I H2 Datenbank starten / Daten in File speichern Java Basics - Anfänger-Themen 25
G jar file lässt sich nicht öffnen Java Basics - Anfänger-Themen 1
N Textdatei aus Resourcen-Ordner eines Projekts/ jar-file lesen Java Basics - Anfänger-Themen 4
J File length als Prüfwert für Download Java Basics - Anfänger-Themen 5
berserkerdq2 Überprüfen ob eine Schreibberechtigung auf ein file exisitert bzw. ob man dieses file löschen kann, wie? Java Basics - Anfänger-Themen 9
berserkerdq2 IOstreams, was unterscheidet file von z. B. BufferedWriter? Java Basics - Anfänger-Themen 11
J Datentypen String in File konvertieren funktioniert nicht Java Basics - Anfänger-Themen 4
A java jar-File Java Basics - Anfänger-Themen 1
E Executable jar file fehler Java Basics - Anfänger-Themen 9
I Upload File zu einem Webservice Java Basics - Anfänger-Themen 17
I ZIP File erstellen Java Basics - Anfänger-Themen 10
LeoDerKek Textdatei in JAR-File Java Basics - Anfänger-Themen 4
Tom/S File Java Basics - Anfänger-Themen 10
AleXusher Mehrdimensionales Array aus txt.file auslesen Java Basics - Anfänger-Themen 4
A Checkstyle - File contains tab characters Java Basics - Anfänger-Themen 2
H Java file nicht gefunden Java Basics - Anfänger-Themen 5
C File speichern Java Basics - Anfänger-Themen 5
C Runnable Jar-File erzeugen Java Basics - Anfänger-Themen 14
C Pfad zu Properties-File bei ResourceBundle Java Basics - Anfänger-Themen 7
F GSON file mit einer List erstellen Java Basics - Anfänger-Themen 2
rafi072001 Lesen aus einem Excel File Java Basics - Anfänger-Themen 10
C Bild in executable JAR File mitgeben Java Basics - Anfänger-Themen 5
K File (png) in Image laden Java Basics - Anfänger-Themen 3
B Inputstream in file schreiben? Java Basics - Anfänger-Themen 23
S Input/Output Reader/Writer finden file nicht Java Basics - Anfänger-Themen 3
T Buffered Stream leert Txt File Java Basics - Anfänger-Themen 3
A 2d Arrays aus txt.file einlesen Java Basics - Anfänger-Themen 16
Dimax In Java File (nicht in Java Projekt) mysql Driver importieren Java Basics - Anfänger-Themen 3
K File wird in der .Jar nicht gefunden Java Basics - Anfänger-Themen 3
E TXT FILE EINLESEN Java Basics - Anfänger-Themen 4
Trèfle EXCEL-File Laufwerkunabhängig einbinden. Java Basics - Anfänger-Themen 1
B HTML File einlesen inkl. Bilder? Java Basics - Anfänger-Themen 2
B Hilfe bei InputStream To File Java Basics - Anfänger-Themen 22
topi relativer Pfad in einem Runnable JAR file Java Basics - Anfänger-Themen 12
A jar File kleiner bekommen Java Basics - Anfänger-Themen 3
B File öffnen in src/main/webapp Java Basics - Anfänger-Themen 4
K File-Name Vergleich Java Basics - Anfänger-Themen 2
krgewb Runnable JAR File Export Java Basics - Anfänger-Themen 11
S Maxium aus einer File finden Java Basics - Anfänger-Themen 12
dapzoo Class File Version zu niedrig? Ausführen über Eingabeaufforderung nicht möglich Java Basics - Anfänger-Themen 14
D Input/Output File exists canRead canWrite Java Basics - Anfänger-Themen 11
B cal4j - Error at line 1:Unexpected end of file Java Basics - Anfänger-Themen 0
P jar file lässt sich nicht ausführen Java Basics - Anfänger-Themen 4
E Best Practice Jar-file mit zwei Klassen und externer Bibliothek über Konsole erzeugen Java Basics - Anfänger-Themen 13
M Erste Schritte CSV-File einlesen und Daten verarbeiten Java Basics - Anfänger-Themen 5
F File von Windowsfreigabe laden Java Basics - Anfänger-Themen 1
S java.nio.file.FileSystemException bei Dateizugriff vermeiden Java Basics - Anfänger-Themen 7
J Zweidimensionales Array in CSV File exportieren Java Basics - Anfänger-Themen 3
E War-File Problem mit Eclipse Java Basics - Anfänger-Themen 3
B Excel File einlesen und Überschrift prüfen Java Basics - Anfänger-Themen 8
M Email versenden Outlook, attached File, ohne Anmeldung Java Basics - Anfänger-Themen 4
M Input/Output Word File Kopieren Java Basics - Anfänger-Themen 12
K Runable Jar File erstellen Java Basics - Anfänger-Themen 17
T Java Executable jar file funktioniert nicht Java Basics - Anfänger-Themen 4
sourcecorn Werte aus einem File lesen Java Basics - Anfänger-Themen 6
Kopak'rraf Korruptes zip File. Java Basics - Anfänger-Themen 0
T File für Einstellungen wird nicht geladen Java Basics - Anfänger-Themen 1
S Sounddatei in Jar File integrieren Java Basics - Anfänger-Themen 2
S Index File bauen Java Basics - Anfänger-Themen 5
T Anzeige, wie lange es noch dauert bis ein File gesendet ist. Java Basics - Anfänger-Themen 2
T filereader , file aus programm einlesen Java Basics - Anfänger-Themen 12
Ghostman1711 Itext PDF print File gelockt by Java Java Basics - Anfänger-Themen 15
N Email mit Anhang - File not Found Java Basics - Anfänger-Themen 1
K Interface Kein Bild im .jar-File Java Basics - Anfänger-Themen 15
S Bild in Jar-File mit ImageIO Java Basics - Anfänger-Themen 50
Syncopated Pandemonium Compiler-Fehler The constructor MP3File(File) refers to the missing type NoMPEGFramesException Java Basics - Anfänger-Themen 7
S File mit canRead() testen Java Basics - Anfänger-Themen 4
A file.delete funktioniert nicht Java Basics - Anfänger-Themen 15
K Classpath Lesen von Property-File Java Basics - Anfänger-Themen 1
S jar file Java Basics - Anfänger-Themen 19
B Fragen zu ZIP-File Java Basics - Anfänger-Themen 9
B Dateityp von File bekommen Java Basics - Anfänger-Themen 2
I Automatisch Verzeichnis erstellen bei File erstellen Java Basics - Anfänger-Themen 5
E Große Datenmengen effizient in CSV File speichern Java Basics - Anfänger-Themen 4
I String zu File umwandeln Java Basics - Anfänger-Themen 2
N File virtuell ByteStream Java Basics - Anfänger-Themen 11
X Übergabeparameter Konstruktor (File) Java Basics - Anfänger-Themen 13
Anfänger2011 file.isDirectory() liefert falschen Wert!? Java Basics - Anfänger-Themen 1
ms_cikar Jar file mit resource erzuegen Java Basics - Anfänger-Themen 28
E lesen csv file column by column Java Basics - Anfänger-Themen 10
U Anhand von Ant ein War-File erstellen Java Basics - Anfänger-Themen 0
B Quellcode einelsen "line by line" (und abspeichern in file (txt) Java Basics - Anfänger-Themen 7
O Zip-File Inhalt einlesen Java Basics - Anfänger-Themen 3
V Erste Schritte Dateinamen aus einer FIle[] in eine List Java Basics - Anfänger-Themen 11
P Jar File Java Basics - Anfänger-Themen 3
B Probleme bei "Daten in CSV File schreiben". Java Basics - Anfänger-Themen 9
S CSV File - "Vergleichen und Sortieren" Java Basics - Anfänger-Themen 3
T Wieso kann ich das jar file nicht starten? Java Basics - Anfänger-Themen 5
S Resourcen-Dateien im Jar-File verfügbar machen (Intellij 14) Java Basics - Anfänger-Themen 14
A Wieso übergibt der nicht die bearbeitete txt file Java Basics - Anfänger-Themen 8
Ruvok Executable Jar File startet nicht Java Basics - Anfänger-Themen 3
R Ini File erstellen Java Basics - Anfänger-Themen 1

Ähnliche Java Themen

Neue Themen


Oben