Laden...

Findicator - Index von Verzeichnissen erstellen und vergleichen

Erstellt von VampireSilence vor 11 Jahren Letzter Beitrag vor 11 Jahren 5.927 Views
V
VampireSilence Themenstarter:in
10 Beiträge seit 2011
vor 11 Jahren
Findicator - Index von Verzeichnissen erstellen und vergleichen

Hallo Zusammen,

ich möchte euch gerne ein Programm vorstellen, dass ich geschrieben habe. Ich hoffe es nützt euch genau so sehr wie mir.

Zusammenfassung
Der Findicator indiziert Dateien und Verzeichnisse und stellt sie in einer Datei zusammen. Danach können die Indizes auch miteinander verglichen werden.

Was kann Findicator ?
Zunächst einmal natürlich Dateien indizieren. Die Indizies können im Programm auch wieder geöffnet und die Verzeichnisstruktur durchsucht werden. Die wohl interessanteste Funktion, ist ein Vorher-Nachher-Vergleich von Verzeichnisstrukturen. Man kann also bspw. nach dem Update eines Programms genau sehen, welche Dateien hinzugefügt, geändert oder gelöscht wurden. Auch wenn Fehler in einem Programm auftreten, kann man auf diese Weise leicht erkennen, ob das Problem an einer der Dateien liegt oder nicht. Ebenso kann man Indizes anderer Anwender zum Vergleich mit eigenen Indizes heranziehen um evtl. Dateifehler zu finden. Und davon abgesehen kann es auch einfach mal interessant sein, zu beobachten was sich auf dem eigenen Rechner so alles tut. 😉

Welche Informationen werden für den Vergleich herangezogen ?
Aufgezeichnet werden der Dateiname, die Größe, sowie die Hashwerte MD5 und SHA1. Jedes Dateikennzeichen kann optional gewählt und aufgezeichnet werden.

Installation/Deinstallation
Das heruntergeladene Archiv muss nur entpackt werden und enthält auch nur eine einzige Datei (Standalone-EXE). Diese kann direkt ohne Installation gestartet und verwendet werden.
Zur Deinstallation muss diese Datei lediglich wieder gelöscht werden. Es werden weder Registry-Einträge, noch Konfigurationsdateien erstellt.
Die Verwendung als portable Applikation ist möglich.

Geplante Features
Wenn genug Interesse besteht habe ich angedacht eine kleine Datenbank aufzubauen, die Indizes frischer Installationen von allerlei Anwendungen enthält und die bei Problemen zum Vergleich mit eigenen Anwendungen herangezogen werden können. So kann man schnell sehen, ob alles korrekt installiert wurde.

Bekannte Probleme
Dateien die gerade beschrieben werden bereiten zum Teil noch Probleme. Die Registry-Dateien sind bspw. noch nicht indizierbar.

Feedback
Ist immer gerne gesehen. 😃

Screenshots
siehe folgende Beiträge

mfg

  • VampireSilence
V
VampireSilence Themenstarter:in
10 Beiträge seit 2011
vor 11 Jahren
Findicator - Index von Verzeichnissen erstellen und vergleichen

Index erstellen

V
VampireSilence Themenstarter:in
10 Beiträge seit 2011
vor 11 Jahren
Findicator - Index von Verzeichnissen erstellen und vergleichen

Index durchsuchen

V
VampireSilence Themenstarter:in
10 Beiträge seit 2011
vor 11 Jahren
Findicator - Index von Verzeichnissen erstellen und vergleichen

Index vergleichen

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo VampireSilence,

das klingt nach einem netten kleinen, sehr brauchbaren Tool.

welche Dateien hinzugefügt, geändert oder gelöscht wurden.

Es wäre nett, wenn du auch doppelte Dateien erkennen würdest bzw. wenn Dateien umbenannt oder verschoben wurden. (Anhand der Hashwerte ist das mit für die Praxis mehr als ausreichender Wahrscheinlichkeit möglich).

Aufgezeichnet werden der Dateiname, die Größe, sowie die Hashwerte MD5 und SHA1.

Zusätzlich das Dateidatum bzw. die Dateidatumse (Create, Change, Access) wären nicht schlecht.

herbivore

16.842 Beiträge seit 2008
vor 11 Jahren

Hi,

vielen Dank für das Bereitstellen der Anwendung.

Zu Deiner Indizierungsmethode: persönlich finde ich sollte eine Größe keine Rolle spielen, wichtig ist einzig und allein der Hash einer Datei - daraus ergibt sich die Größe (siehe Grund unten), sofern es Dir nicht darum geht diese auch noch weiter zu verarbeiten. Damit man nicht unnötig einen Vergleich macht lohnt sich auch noch das Dateidatum, insbesondere LastChange.

Es ist schneller, wenn Du über eine Datei eine Art Raster legst, sodass Du zB für jede 10 MB ein Hash erstellst. So hat eine Datei mit 100 MB 10 Hashes. Vorteil ist dahingehend, dass Du Speicherplatz in der MetaDB (die ich auf eine Embedded DB aufsetzen würde, statt ein XML File) sparst und, dass Du auch Teildateien indizierst - und ganz oben eben die Performance, da Du so parallel arbeiten kannst.

Ich hab mir auch mal erlaubt in den Code zu schauen, da Du ja um Feedback gebeten hast - man sieht Du kommst aus der Java-Ecke 😉 ((Alle Kommetare unter vorbehalt, da der Code ja nicht 1:1 zu bekommen ist)

* Anstatt Deine XML per Regex auszulesen könntest Du das durchaus auch direkt mit XML Implementierungen, zB Linq2XML machen. Die schnellste Variante ist der XmlReader.
* hast ein paar unnötige Castings wie zB string.Format("{0:#,#0}", (object) filesize) oder (object) (bool) (getfilesize ? 1 : 0),
* Wenn es Dir um Performance geht meide DirectoryInfo oder FileInfo und arbeite direkt mit Shell-Befehlen bzw. PInvoke FindFile () NextFile()
* Du könntest sehr viele Schleifen durch LINQ ersetzen, bzw. mit TPL (Parallel.ForEach, PLINQ) arbeiten
* Den schnellsten Weg ein Hash zu berechnen ist über den MemoryStream und einem geeigneten Buffer

Ansonsten denke ich bist Du auf dem Weg was sehr gelungenes aufzubauen!

V
VampireSilence Themenstarter:in
10 Beiträge seit 2011
vor 11 Jahren

Hallo ihr beiden,

erstmal danke für das Feedback 🙂 und nein, ich habe noch nie was mit Java gemacht, aber ich nehme das mal als Kompliment!

Bestimmte Sachen, die ihr angesprochen habt, hatte ich auch schon im Sinn aber wieder verworfen. Ich begründe mal der Reihe nach:

Doppelte/Verschobene Dateien:
Geht. Ich hab sogar nen Code dafür parat, allerdings bedenke welchen Aufwand das machen würde bspw. zwei Windows-Ordner diesbezüglich zu analysieren. Meiner hat gerade etwa 29.000 Dateien und somit n*(n+1)/2 = 420 mio. Vergleiche pro Dateikennzeichen. Da würde der Vergleich zweier Indizes einige Tage(!) dauern. Deshalb hatte ich mich dagegen entschieden.

Zusätzliche Dateikennzeichen (z. B. Änderungsdatum):
Das steht dem Vergleich zweier unabhängig installierter Programme im Weg, da niemals zwei Leute gleichzeitig (und in der gleichen Zeit) das selbe Programm installieren. Externe Indizes würden sich demnach **immer **vollständig von den Eigenen unterscheiden.

Dateigröße indizieren:
Die Dateigröße stellt für mich einen gewissen Sicherheitsaspekt dar, da gezielte Hashkollisionen leichter realisierbar sind, wenn man die Größe der Datei frei wählen kann. Indem ich diese aber zusätzlich aufzeichne kann ich die Möglichkeit eine Datei gezielt zu manipulieren stark einschränken. SHA1 steht ja sowieso schon auf der Kippe und MD5 an und für sich auch schon eine Weile. SHA3 werde ich im Übrigen definitiv als Dateikennzeichen aufnehmen, sobald der Sieger feststeht.

Datei rasterweise indizieren:
Könnte ich machen, würde unter Umständen sogar die Manipulationsmöglichkeiten weiter einschränken, allerdings ist der Nettoindizierungsaufwand doch der Gleiche oder nicht ? Aber mal angenommen du hast Recht, dann geht es immernoch auf Kosten des Speicherplatzes, denn 10 Hashes á 40 Zeichen sind definitiv mehr als einer mit 40 Zeichen. Ansonsten bitte ich um nähere Erläuterungen.

Regex:
Da muss ich dir Recht geben, da hatte ich nicht nachgedacht. Linq und Ähnliches ist für 3 Suchbegriffe im Prinzip aber auch wieder ein Overkill. Am besten schreibe ich mir da nochmal was eigenes, dass die entsprechenden Passagen byte-weise sucht.

Unnötige Castings:
Das mit dem string.Format() stimmt, das sind Altlasten, da ich die Größe ursprünglich in MB angeben wollte und Nachkommastellen brauchte. Werde ich korrigieren. Das mit dem (object)(bool) steht allerdings so nicht im Originalcode und mich wundert es auch, warum das nun so im IL-Code auftaucht. Falls du das ? 1 : 0 meinst, das ist dazu da, um zu überprüfen, ob die Dateigröße überhaupt aufgezeichnet wurde. Wenn du nämlich nur MD5 aufzeichnest und den Index mit einem Anderen vergleichst, der Größe **und **MD5 enthält, ist von mir beabsichtigt, dass nur die MD5-Werte zum Vergleich herangezogen werden, denn sonst ist wieder auf wundersame Weise **alles **unterschiedlich.

DirectoryInfo verwenden:
Naja im Grunde hast du Recht, aber die Klasse ist so schön bequem. 👅
Ich werde mal testen, ob ich mit NextFile() etc. signifikante Vorteile erhalte, denn nach Namen sortieren muss ich dann ja auch wieder selbst. Danach zeigt sich ja, wieviel ich da tatsächlich noch rausholen kann.

Schleifen ersetzen:
Welche denn z. B. ? Ich habe mit TPL ehrlich gesagt noch nie gearbeitet.

MemoryStream:
Ja, stimmt schon. Allerdings muss ich die Datei dann ja auch erstmal überhaupt in den Memory kopieren und damit ist der Vorteil dahin. Habe da schon entsprechende Benchmarks laufen lassen und tatsächlich ist es so, dass die MemoryStream-Variante sogar länger brauchte. Selbst beim Speichern der Indizes nutze ich den MemoryStream einzig und allein deswegen als Zwischenspeicher, um die Anzahl an Schreibzugriffen auf der Festplatte möglichst gering zu halten.

Noch was Allgemeines:
Wenn das Konzept Anklang findet, werde ich demnächst noch eine Upload-Funktion hinzufügen. Freut euch aber nicht zu früh auf Vergleichsmaterial, denn ich muss mir noch überlegen, wie genau ich die Datenbank frei von manipulierten Indizes halte. Vermutlich werde ich warten, bis 10 oder mehr identische Indizes hochgeladen wurden, bevor ich sie freigebe, so macht es das WCG beispielsweise. Ansonsten wenn ihr da bessere Ideen habt, immer her damit.

Edit: Screenshots angefügt.

C
1.214 Beiträge seit 2006
vor 11 Jahren

Doppelte/Verschobene Dateien:
Geht. Ich hab sogar nen Code dafür parat, allerdings bedenke welchen Aufwand das machen würde bspw. zwei Windows-Ordner diesbezüglich zu analysieren. Meiner hat gerade etwa 29.000 Dateien und somit n*(n+1)/2 = 420 mio. Vergleiche pro Dateikennzeichen. Da würde der Vergleich zweier Indizes einige Tage(!) dauern. Deshalb hatte ich mich dagegen entschieden.

Bin mir nicht sicher, ob solche Details überhaupt noch ins Projektforum passen. Ich denke, es geht grad noch.
Das kann man sicher relativ schnell lösen. Du erstellst z.B. von jeder Datei einen Hash, z.B. MD5. Das wird sicher eine Weile dauern bei vielen Dateien, aber nicht Tage. Vor allem mit SSDs sollte es nicht so lang dauern. Die Hashes kann man z.B. in einem Hash Set verwalten und bei einfügen merkst du schnell, dass der gleiche Hash schon drin ist. Dann kann man z.B. noch die Dateigröße vergleichen, geht ja auch schnell (vor allem, wenn du sie eh indiziert hast) und dem Benutzer noch die Möglichkeit geben, wirklich den kompletten Dateiinhalt zu vergleichen, wenn er ganz sicher gehen möchte. Auf jeden sollte die Überpüfung im Speicher, wenn du die Dateihashes schon hast, ganz schnell gehen.

16.842 Beiträge seit 2008
vor 11 Jahren

Doppelte/Verschobene Dateien:
Geht. Ich hab sogar nen Code dafür parat, allerdings bedenke welchen Aufwand das machen würde bspw. zwei Windows-Ordner diesbezüglich zu analysieren. Meiner hat gerade etwa 29.000 Dateien und somit n*(n+1)/2 = 420 mio. Vergleiche pro Dateikennzeichen. Da würde der Vergleich zweier Indizes einige Tage(!) dauern. Deshalb hatte ich mich dagegen entschieden.

Nein das stimmt so nicht ganz. Ich beschäftige mich mit Performance-orentierter Arbeit von Dateien schon etwas länger (siehe auch viele meiner Forenbeiträg diesbezüglich). Ich hab mir auch die System.IO neu geschrieben, da mir die bestehende einfach viel zu langsam ist.

Wenn Du Dir eine MetaDB aufbaust, in der die Raster intelligent angeordnet sind, so kannst Du ein Raster an mehrere Dateien über Beziehungen "binden". Dadurch erkennst Du sehr schnell und effizent, welche Dateien sich ähneln und welche Dateien identisch sind.

Zusätzliche Dateikennzeichen (z. B. Änderungsdatum):
Das steht dem Vergleich zweier unabhängig installierter Programme im Weg, da niemals zwei Leute gleichzeitig (und in der gleichen Zeit) das selbe Programm installieren. Externe Indizes würden sich demnach immer vollständig von den Eigenen unterscheiden.

Wenn Du eine MetaDB effektiv aufbaust, so hinterlegst Du zu jeder Datei das LastChange-Attribut. Diesbezüglich brauchst Du das Raster also nicht neu anlegen, wenn sich dieses Attribut nicht verändert hat (im Vertrauen, dass eine Änderung das LastChange-Datum beeinflusst).

Datei rasterweise indizieren:
...Ansonsten bitte ich um nähere Erläuterungen.

Viele Raster können sich wiederholen. Dadurch hast Du eine Tabelle mit einem Raster-Element, das auf viele Dateien verweisen kann. n-n Beziehung halt.

DirectoryInfo verwenden:
Naja im Grunde hast du Recht, aber die Klasse ist so schön bequem. 👅
Ich werde mal testen, ob ich mit NextFile() etc. signifikante Vorteile erhalte, denn nach Namen sortieren muss ich dann ja auch wieder selbst. Danach zeigt sich ja, wieviel ich da tatsächlich noch rausholen kann.

~850-fach schneller bei SMB-Shares ist für mich ein Argument, das nicht zu kippen ist. ~20-fach bei lokalen Platten.

Schleifen ersetzen:
Welche denn z. B. ? Ich habe mit TPL ehrlich gesagt noch nie gearbeitet.

Raster anlegen und Hashes berechnen. (Hab aktuell keine Möglichkeit den ILCode zu sehen, daher kann ich kein prinzipielles Beispiel liefern)

MemoryStream:

Mein Fehler; ich meine den BufferedStream. Siehe auch [gelöst] Wie große Files schnell einlesen ohne RAM zu verbrauchen?

V
VampireSilence Themenstarter:in
10 Beiträge seit 2011
vor 11 Jahren

Ok, so langsam verstehe ich was du meinst. Ich denke wir haben ein bisschen aneinander vorbei geredet.

Diesbezüglich brauchst Du das Raster also nicht neu anlegen, wenn sich dieses Attribut nicht verändert hat (im Vertrauen, dass eine Änderung das LastChange-Datum beeinflusst). Doch genau das muss ich, denn jeder neue Index liegt in einer neuen separaten Datei. Eine Änderung sehe ich ja dann auch erst, wenn Wochen oder Monate später tatsächlich ein Fehler auftritt und ich die Daten dann mit dem zukünftigen Index vergleiche. Wohl bemerkt zukünftig, d.h. bei der Erstellung dieses Indizes sind mir genau diese Daten ja noch garnicht bekannt.

Viele Raster können sich wiederholen. Dadurch hast Du eine Tabelle mit einem Raster-Element, das auf viele Dateien verweisen kann. n-n Beziehung halt. Ja, genau so kenne ich das von MySQL-Indizes (habe lange Zeit mit PHP/MySQL programmiert, vllt kommt ja auch daher mein Java-ähnlicher Programmierstil) und so war auch die öffentliche Datenbank dann angedacht. Die lokalen Indizes stehen aber wie gesagt alle für sich.

~850-fach schneller bei SMB-Shares ist für mich ein Argument, das nicht zu kippen ist. ~20-fach bei lokalen Platten. Ok, das klingt wirklich vielversprechend, aber vergiss nicht, ich muss noch sortieren. Und darüber hinaus schlagen die Lesezugriffe mit gerade mal ~5% der Gesamtzeit zu Buche. Die meiste Zeit (>90 %) geht für die Berechnung der Hashwerte drauf. Die Gesamtersparnis ist also nicht sehr groß.

ich meine den BufferedStream.

Ok, habe das mal direkt an einem meiner Ordner getestet und folgende Benchmarks erhalten:


FileStream: 			6008 sec
BufferedStream (Buffer: 4 KB): 	4852 sec
BufferedStream (Buffer: 8 MB): 	6404 sec

Werde also nochmal etwas testen müssen, welche BufferSize da am performantesten ist. Prinzipiell scheint es aber wirklich schonmal immens schneller zu sein, danke für den Tipp!

49.485 Beiträge seit 2005
vor 11 Jahren

Hallo VampireSilence,

Bin mir nicht sicher, ob solche Details überhaupt noch ins Projektforum passen

da sollten wir bitte alle aufpassen. Es geht hier teilweise schon (zu) tief in die (Programmier-)Details. Siehe Lizenzbedingungen für die Projekte / Spezielle Regeln für Projekte-Threads.

Doppelte/Verschobene Dateien:

Das geht auch ohne quadratischen Aufwand, mit linearem Aufwand, z.B. mit dem genannten HashSet, aber noch besser mit einem Dictionary<Hash, List<FileIndicator>>, wo zu jedem Hash eine Liste von Dateien/Dateikennzeichen mit diesem Hash gespeichert sind.

Zusätzliche Dateikennzeichen (z. B. Änderungsdatum):

Ob du das Änderungsdatum mit zum Vergleich heranziehst, kannst du z.B. von einer Einstellung oder Abfrage abhängig machen. Aber selbst wenn es nicht zum Vergleich herangezogen wird, sind die Datumse doch eine wichtige Information für den Benutzer, auch wenn sie nur im Statusbereich angezeigt werden.

herbivore

2.891 Beiträge seit 2004
vor 11 Jahren

Noch ein kleiner Hinweis zum Thema "Index", "verschobene/umbenannte Dateien" und insbesondere(!) "Performanz": Das alles bekommt man frei Haus, wenn man das NTFS USN-Journal verwendet (wie es z.B. Everything macht).
Mit System.IO unvergleichlich schneller, da es direkt mit dem NTFS-Index arbeitet, Datei-Hashes gibt es frei Haus (ohne den Dateiinhalt anfassen zu müssen) und Dateisystemänderungen bekommt man durch den integrierten Journal-Vergleich raus.
Code dazu gibt's z.B. unter MFT Scanner.