Ich verwende iTextSharp , um den Text aus einer PDF-Datei zu lesen. Es gibt jedoch Situationen, in denen ich keinen Text extrahieren kann, da die PDF-Datei nur Bilder enthält. Ich lade jeden Tag die gleichen PDF-Dateien herunter und möchte sehen, ob die PDF-Datei geändert wurde. Wenn der Text und das Änderungsdatum nicht abgerufen werden können, ist eine MD5- Prüfsumme die zuverlässigste Methode, um festzustellen, ob sich die Datei geändert hat?
Wenn ja, wären einige Codebeispiele willkommen, da ich nicht viel Erfahrung mit Kryptographie habe.
Antworten:
Mit System.Security.Cryptography.MD5 ist es sehr einfach :
(Ich glaube , dass tatsächlich die Umsetzung MD5 nicht entsorgt werden müssen, aber ich würde wahrscheinlich so trotzdem noch tun.)
Wie Sie die Ergebnisse anschließend vergleichen, liegt bei Ihnen. Sie können beispielsweise das Byte-Array in base64 konvertieren oder die Bytes direkt vergleichen. (Beachten Sie jedoch, dass Arrays nicht überschrieben werden
Equals
. Die Verwendung von base64 ist einfacher, aber etwas weniger effizient, wenn Sie wirklich nur daran interessiert sind, die Hashes zu vergleichen.)Wenn Sie den Hash als Zeichenfolge darstellen müssen, können Sie ihn mithilfe von
BitConverter
:quelle
BitConverter.ToString(md5.ComputeHash(stream)).Replace("-","").ToLower();
.Replace("-", String.Empty)
ist ein besserer Ansatz. Ich habe eine einstündige Debug-Sitzung durchlaufen, weil ich beim Vergleich einer Benutzereingabe mit dem Datei-Hash falsche Ergebnisse erhalte.So mache ich es:
quelle
using
Blöcke wäre nützlich, da das Öffnen einer Datei mit größerer Wahrscheinlichkeit fehlschlagen wird. Ein frühzeitiger / schneller Fehleransatz spart Ihnen die Ressourcen, die zum Erstellen (und Zerstören) der MD5-Instanz in solchen Szenarien erforderlich sind. Sie können auch die geschweiften Klammern der ersten weglassenusing
und eine Einrückungsstufe speichern, ohne die Lesbarkeit zu verlieren.Ich weiß, dass diese Frage bereits beantwortet wurde, aber ich verwende Folgendes:
Wo GetHash :
Wahrscheinlich nicht der beste Weg, aber es kann praktisch sein.
quelle
public static String GetHash<T>(this Stream stream) where T : HashAlgorithm, new() { StringBuilder sb = new StringBuilder(); using (T crypt = new T()) { byte[] hashBytes = crypt.ComputeHash(stream); foreach (byte bt in hashBytes) { sb.Append(bt.ToString("x2")); } } return sb.ToString(); }
Hier ist eine etwas einfachere Version, die ich gefunden habe. Es liest die gesamte Datei auf einmal und erfordert nur eine einzige
using
Anweisung.quelle
ReadAllBytes
ist, dass die gesamte Datei in ein einzelnes Array geladen wird. Das funktioniert bei Dateien mit mehr als 2 GiB überhaupt nicht und übt selbst bei mittelgroßen Dateien großen Druck auf den GC aus. Jons Antwort ist nur geringfügig komplexer, leidet aber nicht unter diesen Problemen. Also ziehe ich seine Antwort Ihrer vor.using
s nacheinander ohne die ersten geschweiften Klammernusing (var md5 = MD5.Create()) using (var stream = File.OpenRead(filename))
einfügen, erhalten Sie eine Verwendung pro Zeile ohne unnötige Einrückung.using
Anweisung erforderlich ist ". war nicht wirklich ein guter Grund, alles in Erinnerung zu lesen. Der effektivere Ansatz besteht darin, die Daten in Daten zu streamenComputeHash
und wenn möglichusing
nur zu verwenden. Ich kann jedoch vollkommen verstehen, ob Sie die zusätzliche Einrückungsstufe vermeiden möchten.Ich weiß, dass ich zu spät zur Party komme, aber einen Test durchgeführt habe, bevor ich die Lösung tatsächlich implementiert habe.
Ich habe einen Test gegen die eingebaute MD5-Klasse und auch gegen md5sum.exe durchgeführt . In meinem Fall dauerte die eingebaute Klasse 13 Sekunden, wobei md5sum.exe bei jedem Lauf ebenfalls etwa 16 bis 18 Sekunden dauerte.
quelle
Wenn Sie den MD5 berechnen müssen, um festzustellen, ob er mit dem MD5 eines Azure-Blobs übereinstimmt, ist diese SO-Frage und Antwort möglicherweise hilfreich: Der auf Azure hochgeladene MD5-Blob-Hash stimmt nicht mit derselben Datei auf dem lokalen Computer überein
quelle