Auswertung vieler Dateien

  • Allgemein

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Auswertung vieler Dateien

    Etwas unglücklich ist der Umstand, dass eine Applikation in ein Ausgabeverzeichnis mehrere Hunderttausend Dateien binnen von wenigen Stunden erzeugt werden. Die Idee ist natürlich regelmäßig die Dateien sinnvoll zu sichern. Das soll hier gar nicht behandelt werden. Allerdings sollen die Dateien, es ist XML enthalten, auch ausgewertet werden. Bei bestimmten IO.SYSTEM.Funktion bekommt auch Visual Basic bereits mit dieser großen Datenmenge Probleme. Die Funktion GetFiles ebenso wie DirectoryInfo können mit diesen Datenmengen umgehen. Dennoch ist die Idee die große Datenmenge nicht in einem Rutsch zu verarbeiten. Wenn jedoch Päckchen gebildet werden muss man sich merken welche Dateien bereits verarbeitet worden sind. Die Idee über das Dateierstellungsdatum abzugrenzen ist hier unglücklich weil die große Anzahl, wie bereits erwähnt, innerhalb von nur 24 bis 48 Stunden, erzeugt werden. Die Idee ist also den Dateinamen in einer Referenzdatei zu schreiben und diese Referenzdatei ständig fortzuschreiben. Wird die Funktion GetFiles angewendet sollen nur noch die Dateien verarbeitet werden, die nicht in der Referenzdatei zu finden sind. Die Referenzdatei wird dazu als STRING ARRAY in den Arbeitsspeicher geholt.

    Dann sollen die STRING.ARRAY.SORT und SUCH-Funktionen verwendet werden. Mir stellt sich nur die Frage ist das performant oder gibt es für das Problem ein grundsätzlich anderen, besseren Ansatz?

    Also das Problem ist eher kein Problem der Programmiersprache als den richtigen Ansatz dafür zu finden :->

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „bop99“ ()

    Große Anzahl von Dateien verursacht immer starken Verlust an Performance von der Festplatte. Eine gute Ordnerstruktur hilft einwenig beim Navigieren, aber sobald man die Dateien anfassen müssen, beginnt das Problem.
    Was für Informationen enthalten die Dateien? Eventuell können diese in einer Datenbank gespeichert werden anstatt in Dateien?
    Hallo erst einmal - nett, dass Du Dir Gedanken machst.

    Nun, zunächst einmal kann ich die Software welche die Dateien erzeugt leider nicht beeinflussen. Leider hat die Software keine Option eine intelligente Ordnerstruktur anzulegen. Sie schreibt einfach die Dateien weg. Aus der Sicht der Software ist das ein Archivordner.

    Die Dateien enthalten XML. Immer wieder muss ich Dateien suchen und dann auswerten. Meine aktuelle Lösung sieht nun vor, dass ich mit GetFiles an die Verzeichnisse gehe. Jede VB-Funktion bzw. .NET-Funktion welche zunächst einmal das komplette Verzeichnis lesen muss um dann eine Antwort liefern zu können (z.B. einfach mal die Anzahl aller Dateien erfahren) braucht ewig lange wenn sie nicht sogar abbricht weil es intern zu einem Überlauf kommt. Also habe ich, wie ich schrieb, mir mal GetFiles angesehen. GetFiles ist relativ zügig.

    VB.NET-Quellcode

    1. Dim di As DirectoryInfo = New DirectoryInfo("d:\test")
    2. For Each lFile In di.GetFiles("*.*")
    3. i = i + 1
    4. Next


    Testweise habe ich in das Verzeichnis einmal 900.000 Dateien erzeugt. Das Konstrukt benötigt ca. 20 Sekunden bis 3 Minuten bis es das erste Ergebnis liefert. Mein Ansatz ist die Schleife nach einer gewissen Anzahl, z. B. nach 20.000 zu unterbrechen. Die bis dahin gesammelten Dateien auszuwerten und gleichzeitig in eine intelligente Ordnerstruktur zu verschieben (copy, compare, delete). Das funktioniert auch recht gut. Wenn man diesen Ablauf mehrfach wiederholt und in der Zwischenzeit keine weiteren großen Dateimengen nachfließen kann man so das große Verzeichnis je Lauf immer ein weiteres Stück abbauen.

    Aber ist das der Königsweg - oder gibt es bessere Ideen?
    Ich würde die bearbeiteten Dateien einfach in ein Unterverzeichnis mit einem entsprechenden Namen verschieben.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    In diesem Fall ist das Verschieben der Dateien vermutlich die beste Option.
    Je nach Anzahl der erzeugten Dateien pro Zeiteinheit würde ich die Dateien stündlich zusammenfassen (oder kleinere Zeiteinheit wie Viertelstunde, etc.)
    Da hilft die die Klasse IO.FileInfo weiter, denn sie stellt das Erstelldatum und Änderungsdatum bereit. Anhand dieser Info kannst Du die Unterverzeichnisse erstellen und die Dateien dahin verschieben.
    Eventuell als weitere Option kannst Du das Tool im Hintergrund laufen lassen und per Timer alle 5 Minuten einmal die Dateien prüfen und verschieben.
    Wichtig ist auch, vor dem Verschieben zu prüfen, ob die Datei gerade erzeugt/verwendet wird, also noch nicht zu Ende geschrieben ist.
    Und was ist wenn du einfach auf ein Event für "neue Datei" reagierst und dir diese nimmst?
    Also nurnoch auf Neuerungen reagierst und diese SOFORT verarbeitest.
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Sorry, wenn ich mich etwas länger nicht mehr gemeldet habe. Also diese FileSystemWatcher-Idee finde ich nicht schlecht. Es stellt sich nur die Frage, habe das gerade einmal im MSDN nachgelesen, ob das funktionieren wird. Es werden immerhin über 800.000 Dateien in 24 Stunden geschrieben und angeblich soll es mit der FSW-Klasse gerade dann Probleme geben, da nur ein recht kleiner Puffer zur Verfügung steht.

    Grundsätzlich hätte ich sonst die Idee, dass eine im Hintergrund permanent laufende Anwendung, wobei ich noch nicht wüsste, wie das aussehen soll (Dienst, Konsolenanwendung, Windowsanwendung), es muss sich mit VS 2012 Express in VB realisieren lassen, das zu überwachende Verzeichnis selber in bestimmten Intervallen zu prüfen und je Lauf eine begrenzte Anzahl von Dateien für welche gilt Erstellungszeitpunkt < (aktueller Zeitpunkt - 5000ms). Mit dieser Variante sollte es kein Problem geben, da die Dateien mit Sicherheit vollständig erstellt sind. Es handelt sich bei dem Verzeichnis um XML-Dateien mit einer Größe von weniger als 20 KB. Das kann m. E. keine 5000ms dauern diese Dateien zu erstellen.

    Diese würde ich dann in ein Archiv kopieren welches Untoerordner mit einer nur begrenzten Anzahl von Dateien bereitstellt. Da hätte ich als Struktur gedacht:

    ARCHIV
    JAHR2010
    ORDNER01
    ORDNER02
    ORDNER03
    JAHR2011
    etc.

    Vom Ablauf würde ich vorsehen
    KOPIEREN
    VERGLEICHEN
    ZIEL ANALYSE XML -> EXPORT-Struktur -> z.B. Datenbankschnittstelle, ...
    DELETE QUELLE

    Jeder Schritt wird nur dann ausgeführt wenn der voran gegangene Schritt erfolgreich durchgeführt wurde.

    Eigentlich habe ich das schon soweit fertig programmiert, als Konsolenanwendung, mal davon abgesehen, dass ich noch nicht die Verzeichnisüberwachung vorgesehen hatte und ich nicht sicher bin ob dann eine Konsolenanwendung angebracht wäre.

    Aber wieso nicht?

    bop99 schrieb:

    Aber wieso nicht?
    Du musst Deinen Ablauf in 2 Schritten organisieren.
    1. Identifizieren der betroffenen Dateien. Ein FileSystemWatcher ist da i.O. Pro Datei ein IO.File.FileInfo-Objekt, das frisst kein Brot, diese Objekte in eine Liste packen.
    2. In einem gewissen Zeitraster diese Liste abarbeiten, alle Dateien seriell. Da sollte es keinen Zoff geben.
    Wenn allerdings die Anzahl der Dateien zu groß wird, denk über Parallelverarbeitung nach.
    In jedem Falle aber die Identifizierung und die Verarbeitung sauber trennen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich verstehe noch nicht so recht was Du mir sagen möchtest. Soll ich eine Multithreadinganwendung programmieren?

    In etwa werden 10 bis 20 Dateien pro Sekunde in das Verzeichnis neu geschrieben. Wenn ich nun das Verzeichnis mit meiner Anwendung leere bekäme das ja der FSW auch wieder mit. Ich mache mir einfach Gedanken, dass er das nicht mehr schafft oder das dann der Puffer überläuft.

    Wenn ich das ohne FSW mache wird mir keine Änderung am Verzeichnis entgehen. Dafür scanne ich dann aber selber regelmäßig das Verzeichnis. Das habe ich bereits mal ausprobiert und funktioniert eigentlich recht gut. Bei einem Volumen von 800.000 Dateien braucht es da zwischen 5 und 10 Sekunden bis ein Ergebnis da ist. Es geht auch nicht darum besonders schnell dieses Verzeichnis abzuräumen. Es geht darum die Dateien sicher in ein Archiv zu verschieben, also ohne Datenverlust und die Dateien gleichzeitig auszuwerten.
    Bei

    bop99 schrieb:

    10 bis 20 Dateien pro Sekunde
    und

    bop99 schrieb:

    einem Volumen von 800.000 Dateien
    kannst Du von uns keine perfekte Lösung erwarten, da musst Du selber experimentieren und eine gute Lösung finden.

    bop99 schrieb:

    Soll ich eine Multithreadinganwendung programmieren?
    Das wäre eine Möglichkeit, die Du testen könntest.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!